pythonUDP發送結構體,對齊到C++結構體

給出程序先:html

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

咱們知道python 使用UDP發送消息,只能發送byte出去。那麼,如何和一個c++(c#)的結構體進行打包和解包呢?使用pack和unpack就能夠了。c++

好比說咱們的結構體是 這樣的json

 

 它們分別是char 和int型的數據。咱們這樣把這個結構體(暫且認爲是結構體吧)打包成字節流:c#

 

 我這樣打包,直接發送出去,字節數爲 1(字符/char)*4 + 4(int) *17 = 32 位。用c++/c#接收,沒有什麼問題的。dom

可是接收的時候,出現沒法對齊的問題。因此咱們對接收的解包格式這樣定義:socket

 

 至於爲何加一個「=」,能夠查閱python的文檔,有詳細的解釋。ide

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

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

相關文章
相關標籤/搜索