python3 сокет программирует howto представляет этот фрагмент кода
class MySocket:
"""demonstration class only
- coded for clarity, not efficiency
"""
def __init__(self, sock=None):
if sock is None:
self.sock = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
else:
self.sock = sock
def connect(self, host, port):
self.sock.connect((host, port))
def mysend(self, msg):
totalsent = 0
while totalsent < MSGLEN:
sent = self.sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def myreceive(self):
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN:
chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
if chunk == b'':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return b''.join(chunks)
где цикл отправки прерывается, если метод socket send возвращает 0.
Логика этого фрагмента заключается в том, что когда метод send возвращает "0 отправленных байт", отправляющая сторона соединения сокета должна отказаться от своих усилий по отправке данных. Это верно для метода recv, где нулевые байты, считанные для сокета в режиме блокировки, должны интерпретироваться как EOF и поэтому сторона чтения должна отказаться.
Однако я не могу понять, в каких ситуациях метод send мог возвращать ноль. Мое понимание сокетов python заключается в том, что send немедленно возвращается из-за буферизации на уровне ОС. Если буфер заполнен, send будет заблокирован, или если соединения будут закрыты на удаленной стороне, будет создано исключение.
Наконец, предположим, что send возвращает ноль без повышения исключения: действительно ли это означает, что все будущие вызовы send будут возвращать ноль?
Я провел некоторое тестирование (хотя использовал только сокет, подключенный к ::1 в OS X) и не смог найти ситуацию, в которой send возвращает 0.
Edit
В HOWTO указано:
Но если вы планируете повторно использовать ваш сокет для дальнейших передач, вам нужно чтобы понять, что на сокете нет EOT. Повторяю: если сокет send или recv возвращает после обработки 0 байтов, соединение было сломана. Если соединение не было сломано, вы можете подождать на recv навсегда, потому что сокет не скажет вам, что ничего нет больше читать (пока).
Очень легко найти ситуацию, в которой recv возвращает 0: когда удаленная (посылающая) сторона вызывает socket.shutdown(SHUT_WR), далее recv на принимающей стороне вернет 0 и не приведет к возникновению каких-либо исключений.
Я ищу конкретный пример, где вы можете показать, что прием 0 нуля из send указывает на сломанное соединение (которое будет продолжать возвращать 0 при отправке.)