著作一覧 |
ちょっとiOS用にネットワークプログラムを書いていたのだが、どうにも解せない。
NSInputStreamからreadすると0が返ってくることがある。いや、ブロックすべきだろう。と不思議になり、まさかサーバがFINを投げているのかな? とtcpdumpを取ると、0が返って来た後もサーバはバシバシpushして来て、それに堂々とackを返している(シミュレータで実行しているので、OSXのターミナルでtcpdumpが取れるのだ)。
でも、シミュレータの実装がおかしいのかな? と、iPadにダウンロードして試してもやはり途中で止まってしまう。
もしかしてイベントを使わなければならないのかな? と試すと、あっと言う間にNSStreamEventEndEncounteredが通知される。シミュレータで実行すると、これまたサーバは呑気にPUSHして来てOSX側はACKを返している(のが延々とサーバの気が済むまで続く)。
何このアプリケーション置いてきぼりストリーム?
こんなおかしな実装は無いだろう(ドキュメントにもNSStreamEventEndEncounteredは、ストリームのお尻で通知とか書いてある)と思うのだが、どうやってもそうなる。
もしかして同じNSInputStreamオブジェクトにopenメッセ―ジを送るとふたたび元のソケットと結合できるかな? とやってみてもエラーになる。閉じられたから後はcloseメッセージを送るしかないようだ。でも、水面下ではサーバにACKを返しまくっているんだよなぁ。で、closeメッセージを送ると、こちらからFIN立てて送るし、ますますわけわからない(FINを送るってことはソケットはちゃんと抱えているわけだが、しかしストリームは尽きたと判断しているというのがわけわからん)。
もしかして、読み込みバッファがフルになると、ソケットのレイヤーでは特に何もしないけど、アプリケーションのレイヤーでは尽きたと判断するってことかなぁ。とすると、どれだけの速度で読み込まなければならないんだろうか(というか、読み込みバッファのサイズはどれだけ用意されてるんだ? 400バイトくらいなんじゃないかというくらいにあっという間にreadメッセージに0が返ったりEndEncoutneredが返ったりするんだけど、拡大するためのメッセージも見つからないし)。(PUSHに対して何も考えずにACKを返しているソケットより下のレイヤーもおかしい。アプリケーションがバッファを空にするまではACKを返さなければ良いわけじゃん)
こういうのがまさにアップルってことなのかなぁ(と不思議に思うのだが、さてどうすべきなんだろうか)。
(と書いてみたが、もちろんはじめてのiOSプログラミングなので徹底的にこちらの実装が間違っている可能性もあり得る)
ジェズイットを見習え |