TCPソケットベースのサーバーでは、パケットをストリーム経由で送信します。パケットは、パケットのバイト数を指定するヘッダーと、それに続くそのバイト数で構成されます。Erlangに精通している人のために、私は単に{packet、4}オプションを設定しています。iOS側では、このメッセージのストリームのサイズを把握したい場合、次のようなコードがあります。
[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG];
これは正常に機能し、次のデリゲートメソッドコールバックが呼び出されます。
onSocket:didReadData:withTag:
次の論理的なステップは、ストリームのサイズを把握することだと思います。これは、次の方法で行います。
UInt32 readLength;
[data getBytes:&readLength length:4];
readLength = ntohl(readLength);
サーバー側で12バイトの文字列をハードコーディングした後、readLengthは実際にクライアントでも12を読み取るため、これまでのところすべて問題ありません。私は次のように進めます:
[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG];
この時点で、コールバックonSocket:didReadData:withTag:
は呼び出されなくなりました。代わりに、読み取りのタイムアウトが発生しています。おそらく、読み取りを適切に処理しなかったために、このデリゲートメソッドが呼び出されます。
- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length
したがって、サーバーは合計で16バイト、4バイトのヘッダー、および12バイトのバイナリストリームを送信します。
エラーは、CocoaAsyncSocketの使用方法にあると確信しています。サイズを把握した後、残りのストリームを読み取る正しい方法は何ですか?
** アップデート **
クライアントを変更しましたが、現在は機能しているようです。問題は、新しいソリューションでのreadDataToLengthのポイントがわからないことです。最初の読み取りを次のように変更しました。
[socket readDataWithTimeout:-1 tag:HEADER_TAG];
コールバックで、次のことを行います。
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
if (tag == HEADER_TAG) {
UInt32 readLength;
[data getBytes:&readLength length:4];
readLength = ntohl(readLength);
int offset = 4;
NSRange range = NSMakeRange(offset, readLength);
char buffer[readLength];
[data getBytes:&buffer range:range];
NSLog(@"buffer %s", buffer);
//[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG];
} else if (tag == MESSAGE_TAG) {
//[sock readDataToLength:4 withTimeout:1 tag:HEADER_TAG];
}
}
つまり、すべてが1つのアトミックペイロードとして入ってくるのです。おそらくこれは、Erlang {packet、4}の動作方法が原因です。そうだといいのですが。それ以外の場合、readDataToLengthのポイントは何ですか?クライアントでメッセージの長さを事前に知る方法はないので、そのメソッドを使用するための良いユースケースは何ですか?