GCDを使った同期通信処理の検討
ステートフルなプロトコルでサーバーと通信を行う時って、
- サーバーに用意されている最大データ数を受信して
- 受信したいデータ数を送信して
- その数分だけのデータを受信して
- 受信完了ステータスを送信
こんな風に、同期モードでシーケンシャルに書きたくなりますよね。これを なんとか実現できないかとあれやこれや調べていましたが、GCDのセマフォを使って非同期の通信をブロックする仕組みを考えてみました。(正確にはNSStreamに対して無駄なポーリングを発生させない仕組みでしょうか)
ソケットオープン
オープン時にセマフォを0で作成する。
読み込みメソッド
メソッドの頭でストリームの状態を確認し、指定データ分の読み取りを試みる。OKならデータを返し、NGならセマフォをwaitする。取得できたら再びデータの読み取り…のループを、成功するかエラーとなるまで繰り返す。
書き出しメソッド
メソッドの頭でストリームの状態を確認し、指定データの書き出しを行う。OKならそのまま返り、NGならセマフォをwaitする。セマフォが取得できたら、再びデータの書き出し…のループを、成功するかエラーとなるまで繰り返す。
handleEvent
NSStreamDelegateのstream:handleEventでストリームの状態変化のイベントを受信。 状態が変わった時にwait中のスレッドが存在する場合にはセマフォにsignalを送って、wait中のスレッドを起こす。
あとは読み取りや書き込みをシーケンシャルで行う処理を、GCDのグローバルキューで非同期実行してやればOKという寸法です。
火曜から悩んでいた通信処理が、なんとか実装できそうな感じです。