挂在Socket.recv上的Python双向TCP套接字
参考这个例子(和):我试图通过使用TCP阻塞客户机和服务器之间的套接字来实现双向通信 我可以通过挂在Socket.recv上的Python双向TCP套接字,python,python-2.7,sockets,tcp,recv,Python,Python 2.7,Sockets,Tcp,Recv,参考这个例子(和):我试图通过使用TCP阻塞客户机和服务器之间的套接字来实现双向通信 我可以通过客户端->服务器或服务器->客户端进行单向通信,但当尝试在服务器和客户端上接收消息时,套接字仍然被阻止或“挂起”。我正在使用一个简单的算法(recvall),它使用recv,将数据包合并到完整的消息中 我知道在发送或读取所有数据之前,套接字都会被设计阻塞(对吗?),但这不就是sendall和recvall要解决的问题吗?为什么在客户端或服务器上禁用recv“解锁”它并使其工作?我到底做错了什么,导致插
客户端->服务器
或服务器->客户端
进行单向通信,但当尝试在服务器和客户端上接收消息时,套接字仍然被阻止或“挂起”。我正在使用一个简单的算法(recvall
),它使用recv
,将数据包合并到完整的消息中
我知道在发送或读取所有数据之前,套接字都会被设计阻塞(对吗?),但这不就是sendall
和recvall
要解决的问题吗?为什么在客户端或服务器上禁用recv
“解锁”它并使其工作?我到底做错了什么,导致插座一直被阻塞
这是我的代码,唯一的根本区别是发送的消息:
recvall(套接字)
(在客户端和服务器之间共享):
server.py
(先运行):
client.py
:
导入套接字
s = socket.create_connection((args.ip, args.port))
try:
s.sendall('hello server')
print recvall(s)
finally:
s.close()
根据我的理解(),主要问题是recv
内部recvall
只涉及检索流(同样地send
只涉及发送流),它没有“消息”的概念,因此不知道何时完成读取。它读取了所有字节,没有返回任何额外的字节,但这并不是消息发送完成的信号,可能还有更多的字节等待发送,否则就不安全了
这就要求我们有一个明确的指标来指示何时停止阅读recv
和send
只涉及流的管理,因此没有消息(我们的“单元”)的概念。对这个问题有一些很好的解决办法。因为我发送的是固定长度的消息,所以在完成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
def recvall(插座):
数据=“”
而len(data)
双向通信现在可以工作了,唯一的问题是客户端和服务器必须知道他们将收到的消息的长度,在我的情况下,这也不是问题。这对我来说是全新的,所以有人请纠正我的术语和概念。您的recvall()函数将累积所有数据,直到TCP连接关闭,这可能是您的程序出现挂起的原因-您没有关闭连接,因此另一端不知道它应该停止读取。(还请记住,在TCP中,没有数据包-您只得到一个字节流)。因此,您可能需要某种发送数据长度的方法,以便您的recvall()函数可以知道要读取多少数据,或者发送一些特殊的内容来结束数据(例如换行符),并让recvall()查找这些特殊数据。如果我必须关闭套接字,然后重新打开它以便从中读取数据,那么这些数据不会丢失吗?它不是连在插座上吗?或者相反,我必须知道消息的大小(我是在试图避免这种情况)?我认为这是
recvall
的重点,它可以一直读取,直到没有更多的字节通过。然后它知道数据已经完成。我不明白为什么这个例子应该是有效的,但这段代码不是。它们几乎是一样的。recvall()不知道您已经发送了“hello client”或“hello server”,这就是您想要发送的全部内容,它会一直按您所说的方式读取,直到没有更多的字节通过,唯一能确知不会有更多字节通过的方法是关闭TCP连接。如果希望recvall()函数在不关闭连接的情况下停止读取,则必须教会它何时停止读取,例如先发送一个长度,然后在读取了那么多字节后让它停止,或者让它停止读取,例如,当它读取换行符时,或者当它读取了固定数量的字节时让它停止
s = socket.create_connection((args.ip, args.port))
try:
s.sendall('hello server')
print recvall(s)
finally:
s.close()
def recvall(socket):
data = ''
while len(data) < MSG_LENGTH:
packet = socket.recv(BUFFER_SIZE)
if not packet: break
data += packet
return data