我有一个客户端服务器通信,我编写了以下服务器来处理传入的消息,但是如果消息大于缓冲区则会丢失。如果消息大于缓冲区大小,我怎样才能收到整个包?有没有可能,或者我必须强制客户端(在最大缓冲区大小的乞讨时发送消息)在缓冲区大小内发送消息?
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>" )
答案 0 :(得分:3)
在处理任何类型的分组化消息格式时,您实际上只有两种选择:
当我说“缓冲区”时,我并不是指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>
实际上不会在消息中发生 - 这会将消息错误地分成两半。