IOS NSInputStream

У меня возникла проблема при использовании NSInputStream. У меня есть клиентское приложение, которое подключается к серверу, после чего сервер начнет повторно отправлять сообщение моему клиентскому приложению через TCP примерно по 1 сообщению в секунду. Сервер просто передает сообщение клиенту, а сообщение имеет формат xml. Сервер отправляет сообщение одним пакетом.

Теперь проблема в том, что когда я читаю байт из NSInputStream, данные усекаются, что означает, что вместо получения 1 полного сообщения я время от времени получаю 2 отдельных данных (частичных xml). Я не могу отлаживать, потому что это уже происходит, когда я читаю байт данных из NSInputStream.

Я использую Wireshark для анализа каждого пакета, который я получаю, и когда это происходит, данные также усекаются, потому что TCP частично передает данные моему клиенту. Я пытался регистрировать каждый частичный байт данных, сумма частичных данных всегда составляла около 1600 байт.

Я понятия не имею, как они спроектировали и внедрили серверную часть, но я знаю, что многие люди подключаются к этому серверу и постоянно получают от него широковещательные сообщения.

Кто-нибудь сталкивается с этой проблемой? Кто-нибудь может помочь? Возможно ли, что данные превышают максимальный размер и разделяются?


person NelsonPunch    schedule 10.01.2013    source источник


Ответы (1)


Это не проблема сама по себе. Это часть дизайна TCP, а также NSInputStream. Вы можете получать частичные сообщения. Ваша задача — смириться с этим фактом, подождать, пока вы получите полное сообщение, а затем обработать завершенное сообщение.

1600 байт - это немного странно. Я бы ожидал 1500 байт, так как это самый большой допустимый пакет Ethernet (или, особенно, где-то около 1472, что является действительно распространенным MTU, за вычетом некоторых заголовков). Или я могу ожидать кратность 1k или 4k из-за буферизации в NSInputStream. Но все это не имеет значения. Вы должны иметь дело с тем фактом, что вы не обязательно будете получать сообщения на их границах.

person Rob Napier    schedule 10.01.2013
comment
Хорошо. да, я должен ждать, пока все части данных не поступят, и объединить их, чтобы они стали одними полными данными, и я делаю это сейчас, но это также приводит к другой проблеме в клиентском приложении, приложение имеет таймер обратного отсчета, и время зависит от данные с сервера. Если я буду ждать каждой части данных, это приведет к тому, что таймер обратного отсчета не будет плавным. - person NelsonPunch; 11.01.2013
comment
Я предполагаю, что сервер был реализован на Java, другая группа людей, работающих над приложением для Android, не сталкивается с такой проблемой. Если TCP автоматически разделяет данные, когда отправитель отправляет данные, будет ли он автоматически восстанавливаться на стороне получателя? - person NelsonPunch; 11.01.2013
comment
Да, TCP автоматически соберет данные, даже если пакеты будут отброшены и отправлены повторно, и даже если пакеты выходят из строя (что случается). Вы не можете ожидать, что пакеты будут приходить к вам с постоянной скоростью в загруженной сети. Библиотеки Java могут буферизовать для вас иначе, чем библиотеки iOS, но использование Java не обеспечит последовательное прибытие сетевых пакетов на сетевой интерфейс. - person Rob Napier; 11.01.2013
comment
Что, если переполнение буфера отправки сервера вызовет такую ​​​​проблему? Этот сервер используется многими пользователями, возможно, более 50 одновременно. - person NelsonPunch; 11.01.2013
comment
50 — это не очень много пользователей для хорошо спроектированного сервера, но да, ваш сервер может быть менее последовательным в том, как он отправляет вам пакеты, если он общается со многими людьми одновременно. Сетевая карта может отправлять только один пакет за раз, поэтому она может отправить один вам, а затем отправить несколько другим людям, а затем вернуться к вам. Это не переполнение, и ничто из того, что вы сказали, не указывает на то, что вы отбрасываете пакеты или что-то в этом роде. Вы просто не можете полагаться на получение пакетов с равными интервалами в системе на основе Ethernet или 802.11 (по сравнению с Token Ring или ATM, которые могут дать вам это). - person Rob Napier; 11.01.2013
comment
Хорошо, вот результат, который я тестировал недавно. на симуляторе, если я использую Wi-Fi для подключения к Интернету, эта проблема появляется. Если я использую кабель ethernet в качестве подключения к Интернету, эта проблема никогда не возникает. Есть идеи? Вот почему эта проблема возникает при работе на физическом устройстве, потому что устройство использует Wi-Fi в качестве подключения к Интернету, а не кабель Ethernet. - person NelsonPunch; 15.01.2013
comment
Это не удивительно. Разные сети, безусловно, могут иметь разные MTU и, безусловно, могут фрагментироваться по-разному. Вы не можете полагаться на то, что большинство сетевых транспортов передают вам пакеты в надежном порядке с постоянными интервалами с предсказуемой фрагментацией. Это не то, что обещают большинство современных сетевых транспортов. Если у вас есть приложение, которое требует этого, вам придется изменить сетевой транспорт на что-то вроде ATM или Token Ring, которые могут обещать эти вещи. Это означает замену сетевого оборудования по всей сети. Вы должны адаптировать свой код к тому, как работают сети. - person Rob Napier; 15.01.2013
comment
Я, ты прав. Похоже, они отправляют все данные в одном пакете, который превышает MTU, поэтому он фрагментируется. Хотя я еще не решил проблему, но спасибо за помощь в поиске проблемы, поэтому я отмечаю ваш ответ как правильный. - person NelsonPunch; 16.01.2013