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 при отправке.)