【发布时间】:2021-10-14 10:24:09
【问题描述】:
由于 TCP 数据包在传输过程中可能会出现碎片,因此您必须调用 recv() 直到它返回 0。这反映在 the python socket documentation 中。
# Echo server program
import socket
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
Python 选择器似乎很酷,但有一个方面让我感到困惑。 example in the docs 建议只调用一次 recv()。
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
在收到对方发送的所有内容之前,我如何才能确保自己阅读?在直接套接字示例中添加循环不起作用,因为这会导致 BlockingIOError。
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
d = bytearray()
while True:
data = conn.recv(1000) # Should be ready
if data:
d.extend(data)
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
break
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
当然,我可以离开 read() 函数并相信我会得到另一个 EVENT_READ,然后将我得到的内容附加到我保存在某处的缓冲区中。但是我如何区分来自客户端的传输?即我如何检测来自客户端的单个 send() 何时结束?使用直接套接字服务器,在我看来,每当我从单个 send() 收到所有内容时,recv() 都会返回 0。
【问题讨论】: