Python 双向 TCP 套接字挂在 socket.recv 上



参考此示例(和文档): https://pymotw.com/2/socket/tcp.html 我正在尝试使用 TCP 在客户端和服务器之间阻塞套接字来实现双向通信。

我可以从client->serverserver->client进行单向通信,但是在尝试在服务器和客户端上接收消息时,套接字仍然被阻止或"挂起"。我正在使用一个简单的算法(recvall),它使用recv将数据包合并到完整的消息中。

我知道套接字在发送或读取所有数据之前一直被设计阻塞(对吗?),但这不是sendallrecvall要处理的吗?为什么在客户端或服务器上禁用recv会"取消阻止"它并使其工作?最终,我做错了什么,导致套接字保持阻塞状态?

这是我的代码,唯一根本的区别是发送的消息:

recvall(socket)(在客户端和服务器之间共享):

def recvall(socket):
data = ''
while True:
packet = socket.recv(16)
if not packet: break
data += packet
return data

server.py(先运行):

import socket
host = 'localhost'
port = 8080
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
while True:
(client, address) = s.accept()
print 'client connected'
try:
print recvall(client)
client.sendall('hello client')
finally:
client.close()

client.py: 导入套接字

s = socket.create_connection((args.ip, args.port))
try:
s.sendall('hello server')
print recvall(s)
finally:
s.close()

根据我的理解(这里的顿悟),主要问题是recvall内部的recv只关心检索流(就像send只关心发送流一样),它没有"消息"的概念,因此不知道何时完成阅读。它读取了所有字节并且没有返回任何其他字节,但这不是消息完成发送的信号,可能还有更多字节等待发送,否则假设是不安全的。

这要求我们有一个明确的指标来指示何时停止阅读。recvsend只关心管理流,因此没有消息的概念(我们的"单元")。本文对此问题有一些很好的解决方案。由于我发送的是固定长度的消息,因此我选择在完成recv之前检查长度是否符合预期。这是recvall的更新版本,请注意必须定义和强制执行MSG_LENGTH以使recvall不会阻塞套接字。

def recvall(socket):
data = ''
while len(data) < MSG_LENGTH:
packet = socket.recv(BUFFER_SIZE)
if not packet: break
data += packet
return data

双向通信现在可以工作了,唯一的问题是客户端和服务器必须知道他们将收到的消息的长度,这在我的情况下也不是问题。这对我来说是全新的,所以有人请纠正我的术语和概念。

最新更新