3

我使用基于 BaseServer 的 UDPServer 来接收碎片 UDP 数据包。

但是有些数据包大于 8192 字节(@handle 方法,打印 len(data)),我无法正确使用它们。

我的原始代码:

class MyUDPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        global arr_len_recv    
        data = self.request[0].strip()
        socket = self.request[1]
        s_recv_paylaod_len = len(data)
        print "s_paylaod",binascii.hexlify(data)

if __name__ == '__main__':    
    server = SocketServer.UDPServer((HOST, LISTEN_PORT), MyUDPHandler)
    tmp = threading.Thread(None, loop_send, None,(param,server) , {})
    tmp.daemon=True
    tmp.start()
    poll=0.1
    server.serve_forever(poll)

所以我使用 RTFM BaseServer、UDPServer、TCPServer。

python SocketServer 文档

我在 SocketServer.TCPServer 示例中找到

class MyTCPHandler(SocketServer.BaseRequestHandler):

        def handle(self):
            self.data = self.request.recv(1024).strip()

但是 self.request 没有 recv 方法

如果您有任何解决方案来修复它或更改 recv 缓冲区的最大限制。

4

2 回答 2

4

最后,我在baseserver python源代码中找到了它:

480 class UDPServer(TCPServer):
481 
482    """UDP server class."""
483
484    allow_reuse_address = False
485
486    socket_type = socket.SOCK_DGRAM
487
488    max_packet_size = 8192

我修改后的主要(见 server.max_packet_size )

if __name__ == '__main__':    
    server = SocketServer.UDPServer((HOST, LISTEN_PORT), MyUDPHandler)
    server.max_packet_size = 8192*2
    server.serve_forever()
于 2013-08-06T20:54:42.247 回答
0

这里涉及到许多因素。

首先,UDP 的最大有效负载大小为 65535。但是,IPv4 标头和 UDP 标头计为 65535 的一部分,因此实际上,最大用户有效负载大小为 65504。

其次,您不能在堆栈中的任何级别接收超过最小的接收缓冲区。我可以解释如何解决这个问题,但我不会,因为……</p>

最后,任何大于单个 MTU 的数据包都会在此过程中被分段。除非这些片段恰好按照它们发送的顺序到达,并且没有任何相当大的延迟,否则它们无法重新组装,因此您将丢失整个数据包。即使在只有 1% 的以太网数据包丢失的连接上,您也可能会丢失超过三分之一的大型 UDP 数据包。很少有应用程序可以接受。

那你该怎么办?好吧,有三个不同的答案:

  1. 建立一个可以保证近乎完美可靠性的专用网络。
  2. 编写您自己的协议以位于 UDP 之上并将大数据包分解为 MTU 大小的数据包。
  3. 只需使用 TCP 而不是 UDP。

在某些情况下,选项 2 是有意义的——例如,对于许多流式 A/V 协议,音频帧、视频 iframe 和元数据都低于 1K,通常可以丢弃而不会产生重大后果,因此不值得付出代价只是使用 TCP 来处理关键帧,因此他们将关键帧分成 1K 块(例如,窗口的矩形部分)或仅为关键帧编写显式的 TCP 式检查和重新发送代码等。

但通常,如果您需要发送大量消息,TCP 会容易得多。

于 2013-08-05T22:27:55.470 回答