#python #objective-c #twisted.internet #nsoutputstream
#python #objective-c #twisted.internet #nsoutputstream
Вопрос:
Я работаю над некоторым сетевым кодом для приложения iPhone, которое взаимодействует с серверной частью Python Twisted. Недавно я столкнулся с проблемой, когда кажется, что либо мой NSOutputStream удваивает полезную нагрузку при отправке, либо twisted удваивает полезную нагрузку при получении.
Я использую «рекомендованный Apple» стиль TCP-сокетов, например, без опроса.
Процесс заключается в следующем:
КЛИЕНТ
— NSStreamEventHasSpaceAvailable: отправить пакет из X байтов данных
— NSStreamEventHasSpaceAvailable: отправить еще один пакет из Y байт данных
СЕРВЕР
— Twisted получает пакет размером (X Y) байт
Я удостоверяюсь, что я явно не отправляю данные, если статус OutputStream равен «NSStreamStatusWriting». Также гарантируется, что отправка данных с клиента запрещена, если не был создан NSStreamEventHasSpaceAvailable.
Есть идеи относительно того, что может быть причиной этого удвоения / слияния полезной нагрузки? Код Twisted довольно прост, используя стандартные данные, полученные в моем протоколе:
получены данные определения (self, data): # выполните логику, чтобы решить, как обрабатывать данные # ... # вывод len (данных) здесь показывает размер объединенного пакета
Код iOS также довольно стандартен:
если (код события == NSStreamEventHasSpaceAvailable) { [OutputStream write:[packet getData] Максимальная длина: [packet getPacketSize]]; } // [packet getData] просто возвращает стандартный массив UInt8. // [packet getPacketSize] возвращает размер этого массива.
Когда приведенный выше код iOS вызывается дважды подряд (например, при отправке двух пакетов один за другим), twisted code сообщает размер объединенных данных.
Заранее спасибо за любые советы или предложения.
Комментарии:
1. возможно, я неправильно понимаю проблему, но tcp — это поток, вы никогда не должны ожидать, что границы буфера на одном конце совпадут с границами другого
2. Я согласен — я не обязательно должен ожидать, что границы буфера совпадут, но я полагаю, что это вопрос предсказуемого поведения. В некоторых случаях, когда я отправляю данные последовательно, они в конечном итоге принимаются как два отдельных вызова «DataReceived» из реакции, когда в других случаях полезные нагрузки объединяются. Просто пытаюсь выяснить, возможно, почему полезные нагрузки иногда объединяются, а не всегда.
Ответ №1:
Я согласен — я не обязательно должен ожидать, что границы буфера совпадут, но я полагаю, что это вопрос предсказуемого поведения.
В коммуникациях на основе TCP не существует предсказуемого поведения; между вами и удаленным хостом может быть любое количество маршрутизаторов, границ NAT, бестолковых прокси или чего-либо еще, что диктует поведение, которое кажется неожиданным.
Черт возьми, там даже могут быть почтовые голуби, переносящие ваши пакеты побайтно.
Однако в реальном мире поведение, как правило, довольно предсказуемо. Но не всегда, никогда в 100% случаев, и всегда с потенциалом какого-нибудь клиента где-нибудь с забитыми трубками.
С TCP вам, по крайней мере, гарантируется, что обычно пакеты будут приниматься в том порядке, в котором они были отправлены, если не произойдет ошибка. Опять же, предполагая, что все точки между ними либо реализованы правильно, либо не являются вредоносными (этот последний бит означает, что вы должны предположить, что иногда данные будут повреждены).
Даже эта гарантия мало что значит; вы можете получить первые 8 из 10 пакетов… или вы можете получить все входящие данные только для того, чтобы обнаружить, что исходящее соединение разорвано, когда вы переходите к ответу….
Итог; ваш алгоритм буферизации с обеих сторон должен предполагать, что буфер может заполняться случайными пакетами, которые полностью не соответствуют размеру данных, застрявших на другой стороне, в первую очередь. Хотя это и не строго обязательно, вашему приложению лучше всего подойдет защита от случайных сбоев соединения; от усеченных буферов, случайно разорванных соединений и повреждения данных.
Поля ранней длины в байтах и контрольные суммы — ваш друг. Предположения — это вы!hjfdahjdas8y!$(amp; ($@#amp;^@#)^amp;! @#amp;_[СОЕДИНЕНИЕ ПОТЕРЯНО]
Комментарии:
1. Спасибо за напоминание =). Эти вещи свежи в моей памяти. Я думаю, я хочу, чтобы TCP действовал как UDP в этом случае. Я не был на 100% уверен, могу ли я рассчитывать на поступление отдельных пакетов независимо от того, как быстро я отправляю их обратно. Я думаю, что я разработал решение для получения желаемого результата — упаковки данных с дополнительной информацией о порядке, размере и т.д., Чтобы проанализировать указанные пакеты, когда они прибудут.