給出程序先: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
急着把消息發出去,因此代碼有點亂,也沒有註釋,嘻嘻。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