На моем сервере на основе TCP-сокета я отправляю пакеты через поток, где пакеты состоят из заголовка, указывающего количество байтов в пакете, за которым следует это количество байтов. Для тех, кто знаком с Erlang, я просто устанавливаю параметр {package, 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];
}
}
Так что все приходит как одна атомная полезная нагрузка. Возможно, это из-за того, как работает Erlang {package, 4}. Я надеюсь, что это так. Иначе какой смысл в readDataToLength? нет способа заранее узнать длину сообщения на клиенте, так в чем же хороший вариант использования этого метода?