我正在使用 python 3.x 和 socket 模块。服务器在 ipv4 地址上运行并使用 tcp。我阅读了一些关于如何发送和接收数据的教程。为了让服务器或客户端确保发送了整个消息,您可以简单地检查发送的数据量是否等于消息的大小:
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
Run Code Online (Sandbox Code Playgroud)
来源:https : //docs.python.org/3/howto/sockets.html#socket-howto
并且为了让客户端确保已收到整个响应,本教程建议在响应的开头添加响应的大小。
我的问题:
编辑:
sock.recv(1024),我的消息只有 500 到 1000 个字符的大小,这不能确保我收到所有消息吗?首先,要发送不需要循环的所有字节,因为 python 套接字提供了一个简单的方法:socket.sendall().
现在回答你的问题:
是的,即使只接收 4 个字节,您也应该有一个接收循环来调用recv()套接字,直到读取 4 个字节。
如果您能保证此类字符不会出现在消息本身中,则可以。但是,您仍然需要搜索您读入的每个字符以获取魔术定界符,因此它似乎不如简单地在消息正文前加上一个长度。
当您调用recv(n)它时,只能保证最多返回n 个字节,而不是正好返回n 个字节。
以下是三种不同的recvall()比较方法:
def recvall(sock, size):
received_chunks = []
buf_size = 4096
remaining = size
while remaining > 0:
received = sock.recv(min(remaining, buf_size))
if not received:
raise Exception('unexpected EOF')
received_chunks.append(received)
remaining -= len(received)
return b''.join(received_chunks)
Run Code Online (Sandbox Code Playgroud)
和更短的
def recvall2(sock, size):
return sock.recv(size, socket.MSG_WAITALL)
Run Code Online (Sandbox Code Playgroud)
最后是另一个版本,它比第一个短一点,但缺少一些功能:
def recvall3(sock, size):
result = b''
remaining = size
while remaining > 0:
data = sock.recv(remaining)
result += data
remaining -= len(data)
return result
Run Code Online (Sandbox Code Playgroud)
第二个很好而且很短,但它依赖于一个套接字选项socket.MSG_WAITALL,我不相信它保证在每个平台上都存在。第一个和第三个应该在任何地方都有效。我还没有真正对任何基准进行比较和对比。
| 归档时间: |
|
| 查看次数: |
3592 次 |
| 最近记录: |