0

我有一个客户端服务器通信,我编写了以下服务器来处理传入的消息,但是如果消息大于缓冲区,它将丢失。如果消息大于缓冲区大小,我如何接收整个包?有没有可能,或者我必须强制客户端(在请求时以最大缓冲区大小发送消息)在缓冲区大小内发送消息?

msg ='' 
while( True ):                 
     msg += server.recv( 20480 )                                    
     aSplit = msg.partition( "</packet>" ) 
     #We received the full message
     while( aSplit[ 1 ] == "</packet>" ):                           
          messagehandler(  aSplit[ 0 ] + "</packet>" )                        
          msg = aSplit[ 2 ]
          aSplit = msg.partition( "</packet>" )
4

1 回答 1

3

在处理任何类型的分组消息格式时,您实际上只有两种选择:

  1. 确保您的缓冲区足够大以处理整个消息。
  2. 编写您的代码,以便它可以解析部分消息。

但是,当我说“缓冲区”时,我指的不是参数 for recv()- 您可以将其设为任意小,然后while多次循环,直到获得完整的消息。

因此,要采用缓冲方法,您可以执行以下操作:

msg = ''
while True:
    msg += server.recv(8192)
    while True:
        aSplit = msg.partition("</packet>")
        if not aSplit[1]:
            break
        messagehandler(aSplit[0] + "</packet>")
        msg = aSplit[2]

这是有效的,因为如果</packet>未找到,则partition()仍然返回一个 3 元组,其中第一项是整个字符串,另外两项是空的。因此,一直partition()为分隔符返回一个非空字符串,然后找到一个数据包。一旦它是空的,就会有一个部分数据包进入msg(或者它是空的),所以我们返回从网络读取,直到我们再次获得整个数据包。

这确实涉及缓冲字符串中的整个消息msg,但这很好,除非您希望这些消息变得非常大(数兆字节) - 例如,如果消息包含大文件,就会发生这种情况。在这种情况下,您需要更聪明一些,例如将数据交换到磁盘或在收到数据时处理数据。

如果我不清楚这些,请告诉我。

编辑:我应该补充一点,确保缓冲区(即msg)不会变得太大通常是个好主意 - 如果确实如此,那么您需要关闭连接,因为出现问题。这会阻止某些东西向应用程序提供无尽的数据,直到系统上的内存意外或恶意耗尽。此外,您需要非常确定字符串</packet>实际上不会出现在消息中 - 这会错误地将消息分成两半。

于 2013-01-10T14:47:36.150 回答