2012-03-12 5 views
0

Я пишу небольшое приложение, которое по сути меняет XML взад и вперед a-la SOAP. У меня есть сервер на базе OS X и клиент iPad. Я использую KissXML на клиенте и встроенный анализатор XML на сервере. Я использую GCDAsyncSocket на обоих для общения.iOS Packet Length

Когда я тестирую свое приложение на симуляторе iPad, вы получаете полный XML. Все работает нормально.

Однако, когда я использую свое устройство разработки (фактическое физическое iPad), все остальное работает нормально, но XML заканчивается после 1426-го символа. Я проверил, что эта ошибка возникает на нескольких iPad.

Когда я подписаться на входящие пакеты на GCDAsyncSocket я использую [sock readDataWithTimeout:-1 buffer:[NSMutableData new] bufferOffset:0 maxLength:0 tag:0]; и ранее только простой [sock readDataWithTimeout:-1 tag:0]; но оба имеют один и тот же результат. Кажется, что GCDAsyncSocket ни в коем случае не виноват, так как исполнение на тренажере прекрасное. Обратите внимание, что 0 в maxLength указывает «бесконечный» буфер.

Кто-нибудь знает, что может быть причиной этого?

+0

Что-нибудь особенное в отношении персонажа 1426 или других предметов вокруг него? Кроме того, '[NSMutableData new]' скорее всего, будет утечка памяти, если не использует ARC. Рассмотрим '[NSMutableData data]'. – Joe

+0

Данные варьируются от передачи до передачи, но всегда заканчиваются в одном и том же месте, а также без имитатора; таким образом, мой вывод о максимальной длине где-то. В качестве побочного примечания программы используют ARC. –

+0

В зависимости от вашей точной настройки сети, [MTU] (http://en.wikipedia.org/wiki/Maximum_transmission_unit) часто бывает около 1400-1500. Сообщения длиннее, чем фрагментированные и отправляются отдельными пакетами. Когда вы работаете на симуляторе, с сервером на том же компьютере, вы не используете физическую сеть, поэтому эффективный MTU намного выше, и вы не получаете фрагментации. Вы уверены, что используете 'GCDAsyncSocket' правильно? Вероятно, вы будете называть 'readDataWithTimeout' несколько раз, а не один раз. –

ответ

2

1426 Звучит очень похоже на MTU (Maximum Transmit Unit), который является максимальным размером данных TCP, которые вы можете отправить. Это разные размеры на разных сетевых носителях и разных конфигурациях, но 1426 довольно распространен.

Это говорит о том, что вы путаете прием TCP-пакета с завершением XML-сообщения. Нет гарантии, что пакеты TCP будут завершены на границе XML-сообщения. GCDAsyncSocket - это низкоуровневая библиотека, которая говорит TCP, а не XML.

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

Кстати, очень возможно, что ваш Mac имеет другой MTU, чем ваш iPad, поэтому вы можете наблюдать за другим поведением на разных платформах.

0

Имея взгляд на код для GCDAsyncSocket, я бы сказал, что вполне возможно, что в нем есть ошибка. Например, если вы читаете безопасный сокет, механизм cfsocket используется вместо обычных дескрипторов файлов стиля Unix на iPhone, и автор может делать недопустимые предположения о закрытии сокета. Поскольку у вас есть исходный код, я бы попробовал пройти через него с помощью отладчика, чтобы убедиться, что конец файла помечен преждевременно.

TCP - это протокол, основанный на потоке. Теоретически размер пакета базового IP-протокола не должен иметь никакого значения, но если вы достаточно быстро прочитаете сокет, вы можете получить свои данные в кусках размера IP-пакета, особенно если IP-стек каким-то образом настроен на использование памяти (угадывая здесь!).

1

Решение заключалось в том, что при отсутствии неуказанного AsyncSocket обращается к следующей строке-возврату. Когда пакет завершается, он действительно возвращает строку.Я использовал (sock моего GCDAsyncSocket объект)

[sock readDatawithTimeout:-1 tag:0]

, но с тех пор перешел к

[sock readDataToData:[msgTerm dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0]

, где msgTerm является внешней постоянной NSString определяется как «\ г \ п \ г \ n "и делится между клиентом и сервером. Это эффективно обходит проблему возврата строки, заканчивающую пакет.

Еще одно примечание относительно этого решения: поскольку я использую протокол SOAP, пробелы не являются проблемой. Однако, если ваш темперамент о прерываниях пробелов, вы можете использовать метод, например [incomingDecodedNsstringMessage stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]], для его очистки.