给出程序先:

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 {}:{} {}".format(self.remoteIP,self.remotePort,connect.__str__())) def print_time(threadName, delay, counter): pass
急着把消息发出去,所以代码有点乱,也没有注释,嘻嘻。
我们知道python 使用UDP发送消息,只能发送byte出去。那么,如何和一个c++(c#)的结构体进行打包和解包呢?使用pack和unpack就可以了。
比如说我们的结构体是 这样的
它们分别是char 和int型的数据。我们这样把这个结构体(暂且认为是结构体吧)打包成字节流:
我这样打包,直接发送出去,字节数为 1(字符/char)*4 + 4(int) *17 = 32 位。用c++/c#接收,没有什么问题的。
但是接收的时候,出现无法对齐的问题。所以我们对接收的解包格式这样定义:
至于为什么加一个“=”,可以查阅python的文档,有详细的解释。