Python TCP缓冲区溢出

Python TCP缓冲区溢出,python,tcp,Python,Tcp,我有一个客户机-服务器通信,我编写了下面的服务器来处理传入的消息,但是如果消息大于缓冲区,它就会丢失。如果消息大于缓冲区大小,如何接收整个包?有没有可能,或者我必须强制客户机(以最大缓冲区大小在begging发送消息)在缓冲区大小内发送消息 msg ='' while( True ): msg += server.recv( 20480 ) aSplit = msg.p

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

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>" )
msg=''
虽然(正确):
msg+=server.recv(20480)
aSplit=msg.partition(“”)
#我们收到了完整的信息
而(aSplit[1]==“”):
messagehandler(aSplit[0]+“”)
msg=aSplit[2]
aSplit=msg.partition(“”)

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

  • 确保缓冲区足够大,可以处理整个消息
  • 编写代码,以便它能够解析部分消息
  • 不过,当我说“buffer”时,我不是指
    recv()
    的参数-您可以将其设置得尽可能小,只需在
    中循环多次,直到得到完整的消息

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

    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]
    
    msg=''
    尽管如此:
    msg+=server.recv(8192)
    尽管如此:
    aSplit=msg.partition(“”)
    如果不是aSplit[1]:
    打破
    messagehandler(aSplit[0]+“”)
    msg=aSplit[2]
    
    这是因为如果未找到
    ,则
    分区()
    仍会返回一个三元组,其中第一项是整个字符串,其余两项为空。因此,
    partition()
    始终为分隔符返回一个非空字符串,然后找到一个数据包。一旦它是空的,
    msg
    (或者它是空的)中就有一个部分数据包,所以我们继续从网络中读取,直到我们再次获得整个数据包

    这确实涉及到在
    msg
    字符串中缓冲整个消息,但这没关系,除非您期望这些消息变得非常大(多兆字节)-例如,如果消息包含大文件,则可能发生这种情况。在这种情况下,您需要更聪明一些,做一些类似于将数据交换到磁盘或在接收数据时处理数据的事情

    如果我对此不清楚,请告诉我


    编辑:我应该补充一点,通常最好确保缓冲区(即
    msg
    )不会太大-如果缓冲区太大,则需要关闭连接,因为出现了问题。这会停止向应用程序提供无休止的数据,直到系统内存意外或恶意耗尽。此外,您需要非常确定字符串
    实际上不会出现在消息内部-这会将消息错误地一分为二。

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

  • 确保缓冲区足够大,可以处理整个消息
  • 编写代码,以便它能够解析部分消息
  • 不过,当我说“buffer”时,我不是指
    recv()
    的参数-您可以将其设置得尽可能小,只需在
    中循环多次,直到得到完整的消息

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

    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]
    
    msg=''
    尽管如此:
    msg+=server.recv(8192)
    尽管如此:
    aSplit=msg.partition(“”)
    如果不是aSplit[1]:
    打破
    messagehandler(aSplit[0]+“”)
    msg=aSplit[2]
    
    这是因为如果未找到
    ,则
    分区()
    仍会返回一个三元组,其中第一项是整个字符串,其余两项为空。因此,
    partition()
    始终为分隔符返回一个非空字符串,然后找到一个数据包。一旦它是空的,
    msg
    (或者它是空的)中就有一个部分数据包,所以我们继续从网络中读取,直到我们再次获得整个数据包

    这确实涉及到在
    msg
    字符串中缓冲整个消息,但这没关系,除非您期望这些消息变得非常大(多兆字节)-例如,如果消息包含大文件,则可能发生这种情况。在这种情况下,您需要更聪明一些,做一些类似于将数据交换到磁盘或在接收数据时处理数据的事情

    如果我对此不清楚,请告诉我


    编辑:我应该补充一点,通常最好确保缓冲区(即
    msg
    )不会太大-如果缓冲区太大,则需要关闭连接,因为出现了问题。这会停止向应用程序提供无休止的数据,直到系统内存意外或恶意耗尽。另外,您需要非常确定字符串
    实际上不能出现在消息内部-这将错误地将消息一分为二。

    当我发送100kB的消息时,我仍然会丢失消息的结尾,这听起来好像您超出了操作系统的缓冲区来存储数据。例如,如果您使用的是TCP连接,那么您可以发送的数据量是有限的—无论您的客户端在做什么,这都适用,它可能一次读取GB,而且这种情况仍然会发生。在发送端,您需要注意
    send()
    中的返回代码,它将告诉您发送了多少数据。您的应用程序必须在循环中不断发送其余部分,直到全部发送完毕。我建议你读一读。特别是,读一读这一节-我引用:现在我们来谈谈套接字的主要障碍-发送和接收在网络缓冲区上运行。它们不一定能处理您交给它们(或期望从它们那里得到)的所有字节,因为它们的主要焦点是han