сокет python: отправка и получение 16 байтов - PullRequest
4 голосов
/ 26 июля 2011

См. Правки ниже.

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

s.sendall('%16d' % len(data))
s.sendall(data)
print(len(data))

отправляет

size = int(s.recv(16))
recvd = ''
while size > len(recvd):
    data = s.recv(1024)
    if not data: 
        break
    recvd += data
print(size, len(recvd))

На одном конце:

s = socket.socket()
s.connect((server_ip, port))

идругое:

c = socket.socket()
c.bind(('', port))
c.listen(1)
s,a = c.accept()

В моем последнем тесте я отправил блок байтов 7973903, а получатель сообщает о размере 7973930.

Почему блок данных получен на 27 байтов?

Любые другие проблемы?

Python 2.7 или 2.5.4, если это имеет значение.

РЕДАКТИРОВАТЬ: Ага - я, вероятно, читаю после окончания буфера отправки.Если оставшиеся байты меньше 1024, я должен только прочитать количество оставшихся байтов.Существует ли стандартная техника для передачи данных такого рода?У меня такое чувство, что я заново изобретаю колесо.

EDIT2: Я облажался, читая следующий файл в серии.Я отправляю file1 и последний блок составляет 997 байт.Затем я отправляю file2, поэтому recv (1024) в конце file1 считывает первые 27 байтов файла 2.

Я начну другой вопрос о том, как это сделать лучше.

Спасибокаждый.Просьба и чтение комментариев помогли мне сосредоточиться.

1 Ответ

2 голосов
/ 23 января 2015

Во-первых, строка

size = int(s.recv(16))

может считывать менее 16 байтов - это маловероятно, я позволю, но возможно в зависимости от выравнивания сетевых буферов.Аргумент вызова recv() - это значение максимум , ограничение на количество данных, которые вы готовы получить.Но вы можете получить только один байт.Как правило, операционная система вернет вам управление, как только будет получен хотя бы один байт, возможно (в зависимости от ОС и от загруженности процессора) после ожидания еще нескольких миллисекунд в случае прибытия второго пакета с некоторыми дополнительными данными, чтобы оннужно только разбудить вас, а не дважды.

Таким образом, вы хотели бы сказать вместо этого (сделать самый простой из возможных циклов; возможны другие варианты):

data = ''
while len(data) < 16:
    more = s.recv(16 - len(data))
    if not more:
        raise EOFError()
    data += more

Это действительноколесо почти каждый изобретает заново, потому что оно так часто нужно.А вашему собственному коду это нужно во второй раз: вашему циклу while требуется его recv() для обратного отсчета, запрашивая все меньшие и меньшие пределы, пока, наконец, он не получит ровно столько обещанных байтов, и не более.*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...