Прочитать неизвестное количество входящих байтов
Мое приложение связывается с сервером по TCP, используя AsyncSocket. Есть две ситуации, в которых происходит общение:
Приложение отправляет серверу что-то, сервер отвечает. Приложение должно прочитать этот ответ и сделать что-то с информацией в нем. Этот ответ всегда имеет одинаковую длину, например, ответ всегда составляет 6 байтов.
Приложение "бездействует", и сервер через некоторое время инициирует связь (неизвестно приложению). Приложению необходимо прочитать все, что отправляет сервер (может быть любое количество байтов, но первый байт будет указывать, сколько байтов следует, чтобы я знал, когда прекратить чтение) и обработать эту информацию.
Первая ситуация работает нормально. 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:
и обработать сообщение, инициированное сервером.