pythonUDP发送结构体,对齐到C++结构体

给出程序先:

import random
import socket
import struct
import threading
import pickle
import json
from struct import *
from time import sleep


class sendMsg:
    def __init__(self):
        self.sendType=b'\x01'#ready
        self.cliType=b'\x01'
        self.lonDir=b'E'
        self.latDir=b'N'
        self.cliNum=1
        self.lonDeg=100
        self.lonMin=100
        self.lonSec=100
        self.latDeg=100
        self.latMin=100
        self.latSec=100
        self.year=2019
        self.month=9
        self.day=6
        self.hour=12
        self.minute=10
        self.second=10
        self.ipFirst=192
        self.ipSecond=168
        self.ipThird=6
        self.ipFourth=108
        self.typeStr='cccciiiiiiiiiiiiiiiii'

    def __str__(self):
        return self.cliNum
class RecMsg():
    def __init__(self):
        self.id=b'\x02'
        self.ipFirst=192
        self.ipSecond=168
        self.ipThird=6
        self.ipFourth=108
        self.port=-1
        self.errorType=b'\x01'
        self.bandWidth=-1
        self.typeStr='=ciiiiici'


class CommunateThread(threading.Thread):  # 继承父类threading.Thread
    def __init__(self, id,packetLoss,socket,localIP,localPort,remoteIP,remotePort,file):
        threading.Thread.__init__(self)
        self.id=id
        self.packetLoss=packetLoss
        self.socket=socket
        self.localIP = localIP
        self.localPort=localPort
        self.remoteIP = remoteIP
        self.remotePort=remotePort
        self.file=file
    def run(self):  # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        connect=False
        while True:
            if not connect:
                self.sendConnect()
            data, addr = self.socket.recvfrom(1024)
            print("接收到{}发送的消息{}".format(addr,data))
            recMes = RecMsg()
            recData = struct.unpack(recMes.typeStr,data)
            print(recData)
            if recData[0]==b'\x01' or (recData[0]==b'\x03' and recData[6]==b'\x01'):
                self.sendFile(recData)
    def readFile(self):
        with open(self.file,"rb") as f:
            data = f.read(1024)
            while data:
                yield data
                data=f.read(1024)
    def sendFile(self,recData):
        ip = "{}.{}.{}.{}".format(recData[1],recData[2],recData[3],recData[4])
        port = recData[5]
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            i =1
            for data in self.readFile():
                p = random.randint(1,100)
                if p<self.packetLoss:
                    continue
                s.sendto(data,(ip,port))
                sleep(0.005)
                i+=1
                if i%1000:
                    print(i," : send to {}:{},1k".format(ip,port))

            print("发送完成,总计发送 {} K".format(i))
        except Exception as e:
            print(e)
    def sendConnect(self):
        connect =sendMsg()
        connect.cliNum=self.id
        data=pack(  connect.typeStr,
                    connect.sendType,
                    connect.cliType,
                    connect.lonDir,
                    connect.latDir,
                    connect.cliNum,
                    connect.lonDeg,
                    connect.lonMin,
                    connect.lonSec,
                    connect.latDeg,
                    connect.latMin,
                    connect.latSec,
                    connect.year,
                    connect.month,
                    connect.day,
                    connect.hour,
                    connect.minute,
                    connect.second,
                    connect.ipFirst,
                    connect.ipSecond,
                    connect.ipThird,
                    connect.ipFourth)
        #data=pack('ccccb',connect.sendType,connect.cliType,connect.lonDir,connect.lonDir,connect.year)
        print(data)
        self.socket.sendto(data,(self.remoteIP,self.remotePort))
        print("send to {}:{}\t\n{}".format(self.remoteIP,self.remotePort,connect.__str__()))
def print_time(threadName, delay, counter):
    pass
View Code

急着把消息发出去,所以代码有点乱,也没有注释,嘻嘻。

我们知道python 使用UDP发送消息,只能发送byte出去。那么,如何和一个c++(c#)的结构体进行打包和解包呢?使用pack和unpack就可以了。

比如说我们的结构体是 这样的

 它们分别是char 和int型的数据。我们这样把这个结构体(暂且认为是结构体吧)打包成字节流:

 我这样打包,直接发送出去,字节数为 1(字符/char)*4 + 4(int) *17 = 32 位。用c++/c#接收,没有什么问题的。

但是接收的时候,出现无法对齐的问题。所以我们对接收的解包格式这样定义:

 至于为什么加一个“=”,可以查阅python的文档,有详细的解释。

中文版:https://docs.python.org/zh-cn/3.6/library/struct.html

英文版:https://docs.python.org/3.6/library/struct.html

猜你喜欢

转载自www.cnblogs.com/superxuezhazha/p/11497895.html