Python сокет отправить EOF - PullRequest
       7

Python сокет отправить EOF

14 голосов
/ 24 сентября 2010

У меня есть простая программа сокетов передачи файлов, в которой один сокет отправляет данные файла, а другой сокет получает данные и записывает в файл

Мне нужно отправить подтверждение после завершения передачииз пункта назначения в источник

код для пункта назначения

s.accept()
f = s.makefile()
f.read(1024)

код для источника

s.connect(('localhost',6090))
f = s.makefile()
f.write('abcd') 
f.flush()

Здесь возникает проблема, поскольку "abcd" не1024 байта, назначение будет блокироваться до получения 1024 байтов
Решение было бы закрыть () сокет, но так как мне нужно подтверждение от пункта назначения, я не могу закрыть сокет.
Как мне указать пункт назначения, чтобы прекратить блокировку?Я думал о написании символа EOF, который я прочитал в Интернете, что «\ x04» - это EOF, но он не работает.
Также, поскольку данные могут быть двоичными, я не хочу использовать метод readline ().

Ответы [ 3 ]

7 голосов
/ 24 сентября 2010

Разработка протокола (соглашение между клиентом и сервером) о том, как отправлять сообщения.Один простой способ - «первый байт - это длина сообщения, за которым следует сообщение».Грубый пример:

Клиент

Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> s=socket()
>>> s.connect(('localhost',5000))
>>> f=s.makefile()
>>> f.write('\x04abcd')
>>> f.flush()

Сервер

Python 2.6.5 (r265:79096, Mar 19 2010, 21:48:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from socket import *
>>> s=socket()
>>> s.bind(('localhost',5000))
>>> s.listen(1)
>>> c,a=s.accept()
>>> f=c.makefile()
>>> length=ord(f.read(1))
>>> f.read(length)
'abcd'
2 голосов
/ 24 сентября 2010

На самом деле вы не хотите использовать маркер 'EOF', если вы намереваетесь отправлять любые двоичные данные через канал. Что произойдет, если ваши двоичные данные содержат эту последовательность байтов? Вы можете «избежать» этого, чтобы предотвратить это, но для этого нужно проверить оба конца, а затем убедиться, что вы также избежали своей escape-последовательности.

Если вы делаете это для какой-то производственной системы, посмотрите вокруг, чтобы увидеть, есть ли сетевой API, который вы можете использовать (что-то вроде FTP, HTTP, SFTP и т. Д.).

Если это школьный или небольшой проект, вам нужно написать протокол связи. Самым простым может быть отправитель для передачи одного двоичного целого числа X (выбрать размер данных и придерживаться его), а затем отправить X байтов двоичных данных. Получатель сначала определяет размер, а затем ожидает только получение такого количества данных. Помните, что если вам нужно отправить больше байтов, чем может передать размер данных X, вам нужно «разделить» данные на части.

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

2 голосов
/ 24 сентября 2010

Запись и чтение из сокета являются отдельными.Вы можете попытаться закрыть сокет для записи и оставить его открытым для чтения.

См. http://docs.python.org/library/socket.html#socket.socket.shutdown

Кроме того, для FTP используется два сокета: один для данных и один для этого.«подтверждение».

Вы бы были счастливее, если бы использовали второй сокет для этих дополнительных метаданных.

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