TCP套接字无法以突发方式发送消息

时间:2014-09-25 09:58:11

标签: python sockets networking tcp

您好我有多个系统使用TCP连接通过消息进行通信。

我的发送功能如下所示

def _send(self, message, dest):

    self.sendLock.acquire()
    message = pickle.dumps(message)
    #sending length
    message_length = len(message)
    self.outChan[dest].send('<MESSAGELENGTH>%s</MESSAGELENGTH>'
                            % str(message_length))

    for message_i in range(0, message_length, 1024):
        self.outChan[dest].send(message[:1024])
        message = message[1024:]

    self.sendLock.release()

接收线程如下所示:

def readlines(self, sock):

    while True:

        msg = ''

        opTag = '<MESSAGELENGTH>'
        clTag = '</MESSAGELENGTH>'

        while not all(tag in msg for tag in (opTag, clTag)):
            msg = sock.recv(1024)

        msglen = int(msg.split(clTag)[0].split(opTag)[1])
        msg = msg.split(clTag)[1]

        while len(msg) < msglen:
            msg += sock.recv(msglen-len(msg))

        self.rec.put(pickle.loads(msg))

从self.rec读取消息后,将向发件人发送确认消息。

我已经实现了自己的缓冲区来控制网络中的流量。在任何时候,我都会发送最近的MAX_BUFFER_SIZE条消息而没有收到确认。

问题在于:当程序启动时,它会发送MAX_BUFFER_SIZE条消息而不等待确认。但是只接收了这些MAX_BUFFER_SIZE消息中的一小部分。

在MAX_BUFFER_SIZE = 5的其中一个模拟中,共发送了100条消息,未收到m2,m3和m4。收到所有其他消息(按发送顺序)。

我怀疑错误是在初始发送爆发中,但我无法弄清楚确切的问题。

1 个答案:

答案 0 :(得分:1)

接收线程中有一些错误:

  1. 在检查收到的开始和结束标记的消息时,您不会附加到已经收到的部分,而是覆盖它。

  2. 检测到邮件长度后,您将丢失已收到结束标记但尚未分析的后续邮件。

  3. 您可能会将多条消息放在self.rec

  4. 这是一个更正的表格,其中的评论解释了这些变化:

    def readlines(self, sock):
    
        msg = '' # initialize outside since otherwise remiander of previous message would be lost
    
        opTag = '<MESSAGELENGTH>' # no need to repeat this in each iteration
        clTag = '</MESSAGELENGTH>' # no need to repeat this in each iteration
    
        while True:
    
            while not all(tag in msg for tag in (opTag, clTag)):
                msg += sock.recv(1024) # += rather than =
    
            msglen = int(msg.split(clTag)[0].split(opTag)[1])
            msg = msg.split(clTag, 1)[1] # split just once, starting from the left
    
            while len(msg) < msglen:
                msg += sock.recv(msglen-len(msg))
    
            self.rec.put(pickle.loads(msg[:maglen])) # handle just one message
            msg = msg[msglen:] # prepare for handling future messages