Python 使用 socket.send() / socket.recv() 发送多个字符串

Python sending mutliple strings using socket.send() / socket.recv()

我正在尝试使用 socket.send() 和 socket.recv() 函数发送多个字符串。

我正在构建一个 client/server,并且 "in a perfect world" 希望我的服务器在拥有时最多调用 socket.send() 函数 3 次(对于某个服务器命令)我的客户调用了 socket.recv() 3 次。这似乎不起作用,客户端挂断等待另一个响应。

服务器:

        clientsocket.send(dir)
        clientsocket.send(dirS)
        clientsocket.send(fileS)

客户

response1 = s.recv(1024)
if response1:
    print "\nRecieved response: \n" , response1
response2 = s.recv(1024)
if response2:
    print "\nRecieved response: \n" , response2
response3 = s.recv(1024)
if response3:
    print "\nRecieved response: \n" , response3

我正在经历将所有字符串连接在一起然后在客户端重新解析它们的繁琐任务,想知道是否有更有效的方法?

编辑: 我的 response1 输出给了我不寻常的结果。我第一次打印 response1 时,它将所有 3 个响应打印在一个字符串中(全部混合在一起)。我第二次调用它时,它自己给了我第一个字符串。以下对 recv 的调用现在是 glitched/bugged 并显示第二个字符串,然后是第三个字符串。然后它开始显示其他命令,但好像它在队列中。

非常不寻常,但我可能会坚持在服务器中将字符串连接在一起,然后在客户端中解析它们

TCP 是一种流式传输协议,没有消息边界。接收方不知道通过一次还是一百次 send 调用发送了一个数据块。你当然不能假设3个sends可以匹配3个recv。因此,您只剩下在接收器处重新组装碎片的繁琐工作。

一种选择是在纯 TCP 流之上分层消息协议。这就是 zeromq 所做的,它可能是减少乏味的一种选择。

您不会像在真实世界的应用程序中那样通过套接字发送 bytes/strings。

您将在套接字之上创建一个消息传递协议,然后将您的 bytes/strings 放入消息中并通过套接字发送消息。

您可能也不会从头开始创建消息传递协议。您会使用像 nanomsg or zeromq.

这样的库

服务器

from nanomsg import Socket, PAIR
sock = Socket(PAIR)
sock.bind('inproc://bob')
sock.send(dir)
sock.send(dirS)
sock.send(fileS)

客户端

from nanomsg import Socket, PAIR
sock = Socket(PAIR)
sock.bind('inproc://bob')
response1 = sock.recv()
response2 = sock.recv()
response3 = sock.recv()

在 nanomsg 中,recv() 将 return 与 send() 发送的内容完全相同,因此 send() 和 recv() 之间存在一对一的映射。使用较低级别的 Python 套接字时情况并非如此,您可能需要多次调用 recv() 才能获取使用 send() 发送的所有内容。

这个问题的答案已经涵盖elsewhere

您的问题有两种解决方案。

解决方案 1: 标记字符串的结尾。 send(escape(dir) + MARKER) 然后您的客户端继续调用 recv() 直到它获得消息结束标记。如果 recv() returns 多个字符串,您可以使用标记来了解它们的开始和结束位置。如果您的字符串包含它,您需要转义标记。记得在客户端也转义。

解决方案 2: 在发送实际字符串之前发送字符串的长度。然后您的客户端不断调用 recv() 直到它读取所有字节。如果recv() returns 多个字符串。你知道它们的起点和终点,因为你知道它们有多长。发送字符串长度时,让您使用固定数量的字节,以便您可以将字符串长度与字节流中的字符串区分开来。你会发现 struct module 很有用。