Прочитать неизвестное количество входящих байтов

Мое приложение связывается с сервером по TCP, используя AsyncSocket. Есть две ситуации, в которых происходит общение:

  1. Приложение отправляет серверу что-то, сервер отвечает. Приложение должно прочитать этот ответ и сделать что-то с информацией в нем. Этот ответ всегда имеет одинаковую длину, например, ответ всегда составляет 6 байтов.

  2. Приложение "бездействует", и сервер через некоторое время инициирует связь (неизвестно приложению). Приложению необходимо прочитать все, что отправляет сервер (может быть любое количество байтов, но первый байт будет указывать, сколько байтов следует, чтобы я знал, когда прекратить чтение) и обработать эту информацию.

Первая ситуация работает нормально. readDataToLength:timeout:tag возвращает то, что мне нужно, и я могу делать с этим, что я хочу. Это вторая ситуация, в которой я не уверен, как ее реализовать. Я не могу использовать readDataToLength:timeout:tag, так как я не знаю длину заранее.

Я думаю, что я мог бы сделать что-то с readDataWithTimeout:tag:, установив тайм-аут на -1. Я полагаю, что это заставляет сокет постоянно слушать все, что приходит. Однако это, вероятно, будет мешать данным, которые поступают в ответ на что-то, что я отправил (ситуация 1). Приложение больше не может отличить входящие данные от ситуации 1 или ситуации 2.

Кто-нибудь здесь, кто может дать мне помочь мне решить это?

1 ответ

Решение

Ваша ошибка в дизайне сетевого протокола.

Если в вашем протоколе нет этой информации, нет никакого способа отличить ответ от инициируемой сервером связи. Кроме того, задержка в сети препятствует надежной работе очевидного подхода, основанного на времени, который вы описали.

Один из простых способов исправить протокол в вашем случае (если сообщения, инициируемые сервером, всегда меньше 255 байтов) - добавить 7-й байт в начало ответа со значением FF.

Таким образом, вы можете прочитать DataWithTimeout:tag: для 1 байта. По истечении времени ожидания повторите попытку, пока не появятся данные. Если получено значение FF, вы читаете еще 6 байтов с readDataToLength:6 timeout: tag:и интерпретировать его как ответ на запрос, который вы отправили ранее. Если это какое-то другое значение, вы читаете сообщение с readDataToLength:theValue timeout: tag:и обработать сообщение, инициированное сервером.

Другие вопросы по тегам