2016-06-15 3 views
3

я в настоящее время передача данных по протоколу TCP/IP в MyServer используя что-то вроде этогопитон мгновенно

for str in lst: 
    data = str + "\n" 
    self._conn.sendall(data) 

Теперь предположим, что мой список имеет следующие две строки в его

1-This is statement 1 in list 
2-This is statement 2 in list 

Мой клиент получает половину строки 2, как это.

This is statement 1 in list 
    This is 

Я бы хотел отправить строку 1, а затем строку 2 в списке отдельно. Я понимаю, что TCP/IP работает таким образом, в котором он будет отправлять все данные, которые можно отправить. Я думаю, что я мог бы задержать после вызова self._conn.sendall(data), но я хотел узнать, какие у меня есть другие варианты. Я не могу вносить изменения в получатель данных, и я могу только вносить изменения в отправителя. Пока что мой единственный вариант - добавить задержку после каждой отправки.

+1

Клиент должен продолжать делать вызовы recv, пока у него не будет всего. Я не знаком с Python, поэтому я не могу дать конкретный ответ. – kicken

+0

Если вам нужен полный контроль над тем, что отправлено в каждом пакете, есть возможность использовать UDP. – Aya

ответ

5

TCP работает с потоками данных, а не с отдельными пакетами. Это похоже на чтение данных из файла. Отправитель помещает данные в свой буфер отправки, и TCP может сам решить, когда его отправить. Время прибытия в принимающее приложение зависит от того, когда данные были отправлены и в (часто непредсказуемых) условиях сети.

Порты TCP могут быть сделаны более предсказуемыми, если вы используете флаг TCP_NODELAY в своем сокете (что-то вроде socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1).Это приведет к тому, что TCP отправит данные, как только он поступит в его буфер. Но, тем не менее, не было бы никаких гарантий по времени прибытия, поэтому любое временное решение может сломаться, по крайней мере, в некоторых случаях.

Решение состоит в том, чтобы разделить поток данных на куски самостоятельно. Существует несколько способов сделать это:

  1. Использовать сообщения фиксированной длины - если все сообщения имеют фиксированную длину, r eceiver просто должен recv() правильное количество байтов, обрабатывать сообщение, а затем ждать того же количества байтов.

  2. Отправлять длину сообщения перед каждым сообщением. Если вы хотите отправить строку «blah», закодируйте ее как «0004blah» или что-то подобное. Приемник будет (всегда) читать первые четыре байта (0004), чтобы выяснить количество оставшихся байтов для чтения. Затем он будет считывать необходимое количество байтов, обрабатывать сообщение, а затем ждать следующего. Это надежное решение, которое также легко реализовать.

  3. Используйте разделитель. Строки в текстовых файлах делятся на символы новой строки (\n). Аналогичным образом вы можете добавить специальный разделитель (или байты) между сообщениями. Например, вы можете определить, что сообщения всегда заканчиваются знаком доллара ($). Затем все получатели должны делать, это читать из сокета байт байтом, пока он не получит знак доллара. Конечно, если вы примете такой подход, вы должны убедиться, что тело сообщений не содержит символ разделителя.

+1

Спасибо за очищение –

0

TCP основан на потоке, а не на отдельных сообщениях. Поэтому вам нужно разобрать конечную точку каждого сообщения самостоятельно. Одна из идей в вашем случае - прочитать, пока не получите новую строку, а затем обработайте линию. Обратите внимание, что вы можете прочитать:

This is statement 1 in list 
This is 

Затем вам нужно проверить, чтобы увидеть, если вы получили новую строку, обрабатывать строки, а затем оставить свой буфер готовы к приему остальные, как это:

This is 
+0

Не могли бы вы привести пример, как я это сделаю? –

+0

@JamesFranco: Конечно: просто прочитайте до 1000 символов в буфер. Разделите буфер на новой строке ('' \ n''). Разберите первые фрагменты N-1 (это полные строки) и сохраните последний фрагмент. Затем продолжайте чтение, добавление буфера и повторение вышеуказанных шагов. –

0

TCP имеет локальный буфер, который не отправляется, пока он не будет заполнен. Вы можете принудительно очистить локальный буфер, чтобы он отправлялся после каждого сообщения, но когда другая сторона получает эти пакеты, они сохраняются в другом локальном буфере, и ваше разделение может исчезнуть. TCP - это поток, использующий его как поток. Вы должны использовать символы разделителя, и когда пакеты получаются, вам нужно отделить сообщения вручную. Если вы хотите большего контроля, используйте UDP-пакеты.

Смежные вопросы