多个TCP标头的Python套接字接收

时间:2015-12-12 06:52:34

标签: python sockets tcp

我是Python的初学者,所以请考虑我不能一次性提供完整的信息。

我的要求是:

我正在实现一个基于Python的套接字接收器。实现已完成,但我必须处理以下消息/数据流:

1)数据流中将包含4种不同类型的消息。每个都有一个消息标题(1-4),我正在使用

type_msg=struct.unpack('B',data[0])[0]

2)第二部分是接下来的4位将根据标题具有每种类型的数据的实际长度。所以,

actual_len = struct.unpack('i', data[1:5])[0]

3)下一部分是处理收到的数据并使用它。接收数据的长度可以通过** rcv_len = len(data)**

获取

我遇到的问题是我收到的数据少于实际长度。我有 delta-length,我使用的是real_len-rcv_len

此后我无法处理代码。到目前为止,接收增量消息然后将其附加到接收数据的最佳方法是什么。我还想将数据写入文件。

我已经阅读过data.append但不太确定如何实现它。我是否应该再次使用 conn.recv(del_len)接收数据或执行其他操作。

任何指导都会非常有帮助。

下面添加代码:

BUFFER_SIZE=40960
import socket
import struct

class mySocket:

def __init__(self, sock=None):
    if sock is None:
        self.sock = socket.socket(
                        socket.AF_INET, socket.SOCK_STREAM)
        self.sock.bind(('', 9988)) 
        self.sock.listen(1)
    else:
        self.sock = sock

def receive_data(self):
    # Wait for a connection
    print >>sys.stderr, 'waiting for a connection'
    conn, client_address= self.sock.accept()
    print "Connected to client with IP---->", client_address
    while True:
        data = conn.recv(BUFFER_SIZE) 
        if not data:
            print "Connection is Broken.."
            break
        else: 
            if data<5:
                print "MSG HEADER STILL NOT COMPLETELY RECEIVED"
            else:
                type_msg=struct.unpack('B',data[0])
                msg_type = type_msg[0]
                rcv_len = len(data)
                actual_len = struct.unpack('i', data[1:5])[0]
                print "Received Length: ",rcv_len
                print "Actual Length : ",actual_len
                if msg_type == 1:
                    f_cfg = open("test.xml", "wb")
                    if rcv_len < actual_len:
                        del_len = actual_len-rcv_len
                        print "Delta length :",del_len
                        while (del_len):
                            print "Receiving Falcon Config File..."
                            print "Actual Length : ",actual_len,"and total length now is",rcv_len+del_len
                            f_cfg.write(data[5:rcv_len]+data[del_len]) //Feel something wrong in this.
                    else:
                        print "Writing Falcon config"
                        f_cfg.write(data[5:])
                    f_cfg.close()
                else:
                    print "INVALID MESSAGE TYPE. DATA CORRUPTED !!"
                    break

    conn.send("Data Received")
    conn.close()

1 个答案:

答案 0 :(得分:0)

你非常接近。这些技巧永远不会读取任何步骤所需的数据,因此您不必担心过度拍摄。只需通过减去每次收到的金额来跟踪剩余的数据,这样您就不必处理多个变量。

这是一个将在固定大小的缓冲区中读取的帮助程序。用它来读入标题。

def recv_exactly(sock, count):
    """receive exactly count bytes from socket. If socket is closed,
    empty string is returned even if some data received.
    """
    buf = []
    while count:
        data = sock.recv(count)
        if not data:
            return ''
        count -= len(data)
        buf.append(data)
    return ''.join(buf)

您可以使用相同的函数读取数据,但最好随时编写文件。请注意,在接收数据时,min函数用于决定recv大小。

def receive_data(self):
    # Wait for a connection
    print >>sys.stderr, 'waiting for a connection'
    conn, client_address= self.sock.accept()
    print "Connected to client with IP---->", client_address
    while True:
        # read fix length header
        data = recv_exactly(conn, 5) 
        if not data:
            print "Connection is Broken.."
            break
        msg_type, data_len = struct.unpack('Bi', data)

        if msg_type == 1:
            # read stream into file
            with open('test.xml', 'wb') as fp:
                while data_len:
                    # read next chunk. on the last chunk, limit recv to the
                    # known amount of outstanding data
                    data = conn.recv(min(data_len, BUFFER_SIZE))
                    if not data:
                        print "ERROR: TOO FEW BYTES RECEIVED"
                        break
                    fp.write(data)
                    data_len -= len(data)

    conn.send("Data Received")
    conn.close()