2015-12-12 49 views
0

我是一名Python初学者,所以请考虑一下我将无法提供完整的信息。Python套接字接收多个TCP头文件

我的要求是:

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

1)数据流将在其中包含4种不同类型的消息。每一个都具有其中我使用

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

2)第二部分获取消息报头(1-4)是下一个4个比特将根据报头具有每种类型的数据的实际长度。所以,

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

3)下一部分是处理收到的数据,并与它一起玩。收到的数据的长度可以通过** rcv_len = len(数据)**

我面临的问题是,我收到的数据少于/多于真实长度。我有增量长度,我已经使用actual_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() 

回答

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() 
+0

感谢您的精心解答...我会尽力回复这个。 – AB2328

+0

可以请你告诉我如何处理接收部分,当我必须检查2个不同的msg_type ..还有** msg_type,data_len = struct.unpack('Bi',data)**,我得到**“ struct.error:unpack需要长度为8的字符串参数**错误。 – AB2328

+0

我忽略了考虑填充 - 默认情况下,结构将在B之后添加3个字节以在32位边界上对齐。你可以用一个修饰符'='(原生字节顺序),'<(小端),'>'(大端),'!'(网络顺序)来改变它。既然你的格式字符串'“i”'是本地命令,你可以使用'“= Bi”'。由于这是一个网络协议,所以使用'!'代替它是有意义的,但只有在发送端产生流量的代码执行相同的操作时才有意义。 – tdelaney