著作一覧 |
STXではじまってETXで終わるのって、そろそろやめにして欲しいな。
というところから始めて、結局はパケットの区切りを知りたいのだが、TCPだとUDPと違ってストリームだからやっぱりなんらかの区切りが必要となるわけで、それをどうつけるのがスマートだろうか?
1. 改行区切り
テキストベースならそれはありだろうけど。
2. 長さを指定
これは一番まっとうかな。例:HTTP。Content-Lengthとかチャンクの場合のボディの先頭とか。
3. 構造
たとえばXMLを無手順で流すとかいったら、受信側でDOMを組み立てながルート要素の終了タグまで。
ところが、これらと、STX−ETXの一番の違いは、途中でおかしくなった場合の辛さがある。STX-ETXがバッファ溢れとかがありえる通信用だということと関連してるのだろう。
改行区切りだとお尻はわかるが、そのメッセージの先頭が本当にメッセージの先頭かどうやって知るのだろうか? 無理だな。
長さを指定って、その長さの部分を読めていなかったら、1メッセージを落とすという判断はほぼ無理だろう。
構造も同じ。もっともXMLだとXML宣言の出現(XMLのコンテント内にXML宣言がエスケープされずに出現することはありえない)で先頭を見つけることができる。
単純なリクエスト−レスポンスだとお尻を見つけることが重要だけど、障害のパターンをいろいろ考え、かつ行き続けなければならないとしたら、メッセージの先頭を見つけるのもやはり重要だ。
送信側は受信側のエラーを気にせず、定期的にメッセージを垂れ流し続けるようなシステムが上での前提となる(たとえば、listenして得たクライアントのソケットをリストに入れておいて、メッセージの発生元はクライアントからの応答なしに順に送信するような場合。TCP/IPのレイヤーで確定応答だからそういうのもないわけではない)。
エンド2エンドのアプリケーションレイヤーでの確定応答方式というのは楽だけど、TCP/IPのように下の層による保証がないとやはりうまくいかない。HTTPだとRFCで下層に保証を求めているけど、確かにこのプロトコルをUDPでやるのは大変そうだ。
#実際にパケット抜けがありまくって大変なことになった経験が、IPマルチキャストを使ったときにあった。メッセージのフォーマットは重要。
とかつらつら考えると、STX−ETXサンドウィッチってそう悪くはないかも。キャラクターベースだったら、BOMが使えそうだな(でもお尻はないか)とか。
でも、TCP/IPでもそれを持ち込むのはいかがなものか、とか。元々はRS232C上で使っていたフォーマットをそのまま持ち込んだんだろうけど。
#IPマルチキャストでかつ信頼性を上げるための肝は、いちばん処理速度が遅くてパケットの取り損ねがありえるノードを基準にしないとだめだというあたりだったり。
実践 Ruby on Rails Webプログラミング入門―無駄なく迅速な開発環境(将之, 伊尾木)
紹介ではJavaを強調してるなぁ。実物は見てないからそれ以上のことはわからないけど。
著者群の中にRubyistと相性が悪そうな人の名前があるのがちょっと気になる。けど翻訳じゃないから関係ないか(実際、署名原稿で首をかしげた記憶はない)。
#このメンバーだとXP本というわけではないのだろうか?
ジェズイットを見習え |
定石が知りたいですねー<br>昔はTCPストリーム - ETX/STX(エスケープ有) - (バイナリ)メッセージ というレイヤ構造でやってましたが、ETX/STXの部分がとても(感覚的に)イヤンでした。
「元々はRS232C上」というのを見て、<br>プロトコルとしてはPPPを思い浮かべました。<br>PPPover(TCPorUDP) だと何か違う気もしますが<br>PPPのプロトコルで定義されている状態遷移は参考になるのではないかと
なるほど。PPPって見たことない(使ったことはあるけど)ので、見てみます(今回の件は決まったフォーマットだから変えられないけど)。どうもありがとうございます。
PPP とは。私もメッセージの区切りを一般的にはどのように処理しているのか知りたかったところです。<br>ちなみにいまの仕事では TCP の仕様と同じようにシーケンス番号をつけるようになっています ^^;
どゆときに途中でおかしくなるのですか?
バグ。バグ以外の例だと上に書いてあるようなサーバの実装とか。<br>で、バグがおきようがなんだろうが稼動し続けて自動復旧しなきゃならないことがままある。ってことです。<br>あと、サーバーが実はサーバーに接続されたデバイスからの入力を垂れ流してる場合(だからまあSTXが付いたりするのもしょうがないんだけど)。
というか、本文内で2つの全然異なる種類のことについてごちゃまぜになってるな。
あうあう。たぶん私がちゃんと理解できてないんだと思うのですが、「バグがあるらしいけど、STX-ETXのところはバグがないから大丈夫」って意味ですか?
違いますよ。バグでメッセージを読み飛ばしたとか、途中でわけがわからなくなったときに、STXが出てくるまで読み飛ばせるということです(この場合、メッセージの最後を探すのはあまりうまくないというのは、送信側が途中で送信を打ち切った可能性があるから)
あるいはバグを誤解してるのかな? このてのプログラムでありえるバグって処理が遅延した結果イベントハンドラがつまってワーカスレッドがあふれて(.NETだとあり得る)例外になったときとか(キューを使えばすむけど)(で、その非同期IOハンドラがいなくなって非アクティビティタイムアウトを検出して再度非同期IOをかけ直すとか)、同じく非同期IO処理中にスレッドが競合して妙な読み方したときとか、(昔やったけど)WindowsメッセージがDlgMessageにまぎれて消えたとか(違うかも、あいまい)そんな感じ。<br>バグがあるらしいけど、じゃなくて、まだ発現してないバグが稼動時に見つかった場合の話です。
いやあ、非同期IO+マルチスレッドってのは、本当に漢の世界だなぁと書いていてつくづく。まだまだ修行が足りないです。
えっと、STXがメッセージの先頭以外には現れないことをあてにしてもよいくらいには信頼性できるプログラムたちってことですか?
そうです。というか、それが信頼できなければ通信できないと思うけど。
いや、関係ないな。STXが間違った位置に出てきても、問題ないじゃん。どうせそれは間違ったメッセージなんだから、次のSTXでリセットできる。
>機械猫本<br>機械猫本だなんて、と、とと、とんでもないですよー。いや、謙遜じゃなくてですね・・・・・・はい。機械猫本なら・・もっと・・・はい。。。
機械猫本はもっと濃い……と(メモメモ)