簡體   English   中英

Python:套接字發送結構(以C構造為例)

[英]Python : Socket Sending Struct(having C stuct as Example)

下面是C語言的結構,我嘗試轉換為Python,並使用Socket發送結構

C:

        struct CommandReq
        {
            char    sMark[6];  //start flag\r\n*KW
            short   nPackLen;  //packet length
            short   nFlag;     //command ID 0x0002
            int     nGisIp;    //GIS port
            short   nPort;     //GIS Port
            char    sData[50]; //command string
            char    sEnd[2];   //end flag "\r\n"
        };
        //source code
        CommandReq stResq;
        memset(&stResq, 0, sizeof(stResq));
        sprintf(stResq.sMark, "\r\n%s", "*KW");
        stResq.nFlag = 0x0002;
        stResq.nPackLen = sizeof(stResq);
        stResq.nGisIp = 0;
        stResq.nPort = 0;
        strcpy(stResq.sData, "*KW,CC09C00001,015,080756,#");
        strncpy(stResq.sEnd, "\r\n", 2);

我使用namedtuple創建了Python結構,並使用套接字發送了該結構。 但不幸的是失敗了。

蟒蛇:

from collections import namedtuple
MyStruct = namedtuple("MyStruct", "sMark nPackLen nFlag nGisIp nPort sData sEnd")

編輯,回復下面的答案

弄清楚之后,必須在python 3.x中添加字符串.encode(“ ascii”)

      format_ = "6shhih50s2s"
      MyStruct = namedtuple("MyStruct", "sMark nPackLen nFlag nGisIp nPort sData sEnd")
      tuple_to_send = MyStruct(sMark="\r\n{}".format("*KW").encode("ascii"), 
                 nPackLen=struct.calcsize(format_),
                 nFlag=0x0002,
                 nGisIp=0,
                 nPort=0,
                 sData= "*KW,NR09G05133,015,080756,#".encode("ascii"),
                 sEnd="\r\n".encode("ascii"))
      string_to_send = struct.pack(format_, *tuple_to_send._asdict().values()
      socket.sendto(string_to_send, self.client_address)

附加問題

下面是數據包與結構發送

format_ = "6shhih50s2s" //total bytes should be 68 bytes?
    0d0a2a4b5700 //6 char \r\n*KW
    4600 // packet length 70 bytes
    0200 //command ID 0x0002,short 2 bytes
    00000000 //GIS port is integer 4 bytes
    0000 //GIS Port short 2 bytes
    0000 //unknown??what is this?
    2a4b572c4e5230394730353133332c3031352c3038303735362c230000000000000000000000000000000000000000000000 //sData[50] char 50 bytes
    0d0a //sEnd 2 char,2 bytes

2個未知字節怎么來?

namedtuple不能真正與c結構媲美。 如果您習慣使用結構,可以查看struct -module來將結構化信息轉換為字符串。

通常,Pythonistas傾向於使用pickle -module進行序列化。

from collections import namedtuple
import pickle # or cPickle, it's faster
MyStruct = namedtuple("MyStruct", "sMark nPackLen nFlag nGisIp nPort sData sEnd")

tuple_to_send = MyStruct(sMark="abcdef", nPackLen=...)
string_to_send = pickle.dumps(tuple_to_send)

泡菜有兩種口味, picklecPickle 后者更快,但是僅在CPython中可用(大多數程序員使用),而pickle在Jython,IronPython等中也可用。

如果您想堅持使用struct(例如,因為另一端希望使用這種格式),則格式字符串將為

format_ = "6shhih50s2s"

因此,您可以執行以下操作:

import struct
from collections import namedtuple

format_ = "6shhih50s2s"

MyStruct = namedtuple("MyStruct", "sMark nPackLen nFlag nGisIp nPort sData sEnd")
tuple_to_send = MyStruct(sMark="\r\n{}".format("*KW"), 
                     nPackLen=struct.calcsize(format_),
                     nFlag=0x0002,
                     nGisIp=0,
                     nPort=0,
                     sData= "*KW,NR09G05133,015,080756,#",
                     sEnd="\r\n")


string_to_send = struct.pack(format_, *tuple_to_send._asdict().values())

順便說一句:namedtuple是不可變的,即您不能做

tuple_to_send.sMark = "bcdefg"

更改一些屬性。 如果需要這種行為,則必須創建一個類。

編輯

對於Python 3,字符串處理已更改。 必須執行從Unicode到字節的轉換,例如

import struct
from collections import namedtuple

format_ = "6shhih50s2s"

MyStruct = namedtuple("MyStruct", "sMark nPackLen nFlag nGisIp nPort sData sEnd")
tuple_to_send = MyStruct(sMark="\r\n{}".format("*KW").encode("ascii"), 
                     nPackLen=struct.calcsize(format_),
                     nFlag=0x0002,
                     nGisIp=0,
                     nPort=0,
                     sData= "*KW,NR09G05133,015,080756,#".encode("ascii"),
                     sEnd=b"\r\n")


string_to_send = struct.pack(format_, *tuple_to_send._asdict().values())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM