当前位置: 首页 > 面试题库 >

Python套接字接收-传入的数据包始终具有不同的大小

伍玮
2023-03-14
问题内容

我正在将SocketServer模块用于TCP服务器。我在此recv()函数遇到一些问题,因为传入的数据包总是具有不同的大小,所以如果我指定recv(1024)(我尝试使用更大的值,并且更小),则它在2或3个请求后卡住,因为数据包长度会变小(我认为),然后服务器卡住直到超时。

class Test(SocketServer.BaseRequestHandler):

def handle(self):

   print "From:", self.client_address

   while True:

     data = self.request.recv(1024)
     if not data: break

     if data[4] == "\x20":              
       self.request.sendall("hello")
     if data[4] == "\x21":
       self.request.sendall("bye")
     else:
       print "unknow packet"
   self.request.close()
   print "Disconnected", self.client_address

launch = SocketServer.ThreadingTCPServer(('', int(sys.argv[1])),Test)

launch.allow_reuse_address= True;

launch.serve_forever()

如果客户端通过同一源端口发送多个请求,但服务器卡住,则非常感谢您的帮助,谢谢!


问题答案:

网络 总是 不可预测的。TCP使许多这种随机行为为您消除。TCP要做的一件奇妙的事情:它确保字节将以相同的顺序到达。但!它 不能
保证它们会以相同的方式切碎。您根本 无法 假设连接一端的每个send()都会导致远端上的一个recv()的字节数完全相同。

当您说时socket.recv(x),您的意思是“直到您从套接字读取了x个字节后,才返回”。这称为“阻止I /
O”:您将阻止(等待)直到您的请求得到满足。如果协议中的每条消息都恰好是1024字节,则调用socket.recv(1024)将非常有用。但这听起来不对。如果您的消息是固定的字节数,只需将该数字传递给socket.recv()您就可以了。

但是,如果您的邮件可以具有不同的长度怎么办?您需要做的第一件事:停止socket.recv()使用明确的电话号码。改变这个:

data = self.request.recv(1024)

对此:

data = self.request.recv()

recv()只要获得新数据,均值将始终返回。

但是现在您遇到了一个新问题:您怎么知道发件人何时向您发送了完整的消息?答案是:您不知道。您将必须使消息的长度成为协议的明确部分。最好的方法是:为每个消息加一个前缀,长度可以是固定大小的整数(使用socket.ntohs()socket.ntohl()Please转换为网络字节顺序),也可以是字符串后跟一些定界符(例如‘123:’)。第二种方法通常效率较低,但在Python中更容易。

Once you’ve added that to your protocol, you need to change your code to
handle recv() returning arbitrary amounts of data at any time. Here’s an
example of how to do this. I tried writing it as pseudo-code, or with comments
to tell you what to do, but it wasn’t very clear. So I’ve written it
explicitly using the length prefix as a string of digits terminated by a
colon. Here you go:

length = None
buffer = ""
while True:
  data += self.request.recv()
  if not data:
    break
  buffer += data
  while True:
    if length is None:
      if ':' not in buffer:
        break
      # remove the length bytes from the front of buffer
      # leave any remaining bytes in the buffer!
      length_str, ignored, buffer = buffer.partition(':')
      length = int(length_str)

    if len(buffer) < length:
      break
    # split off the full message from the remaining bytes
    # leave any remaining bytes in the buffer!
    message = buffer[:length]
    buffer = buffer[length:]
    length = None
    # PROCESS MESSAGE HERE


 类似资料:
  • 当我尝试接收大量数据时,它会被切断,我必须按enter键才能获取其余数据。起初,我可以增加一点,但它仍然不会收到所有的。正如您所看到的,我增加了conn.recv()上的缓冲区,但它仍然无法获取所有数据。它会在某一点切断它。我必须在原始输入上按enter键才能接收其余数据。我是否可以一次获取所有数据?这是密码。

  • 我正在编写原始套接字客户端(成功发送UDP数据包)和一个服务器套接字,问题出在服务器部分。 Im按以下方式创建套接字:

  • 我使用Android应用程序通过TCP套接字与同一局域网上的PC java应用程序进行通信、发送和接收消息。下面是我在android中使用的Asynctask的代码,用于发送消息并从PC接收回复: } 我在onPostExcecute中的祝酒词中显示PC的回复。 Android通过BufferedWriter发送消息,而PC上的java应用程序在BufferedReader中接收消息。 PC在收到

  • 我使用Python SSL套接字echo测试自签名证书博客测试了一个简单的SSL套接字连接。我生成了一个自签名证书,并使用上面的Python代码进行了尝试。 一切都如描述的那样工作,但问题是,当我使用Wireshark监视网络数据包时,我看不到任何SSL通信量。我所看到的只是普通的TCP数据包,但我希望看到SSL协议被使用。我是不是漏掉了什么? 为了完整起见,我添加了以下代码: Wireshark

  • 我正在构建一个简单的客户端-服务器多人游戏,我想连接UDP套接字。但是,当我调用方法时,它会生成

  • 因此,我正在用Java编写一个程序,在DatagramSocket和DataGramPacket的帮助下发送和接收数据。问题是,当我发送数据/接收数据时,数据在我发送的程序中也会有所不同,但只是在某些情况下,比如: 但有时会起作用,比如: