学习笔记(13):Python网络编程并发编程-解决粘包问题-终极版本
立即學(xué)習(xí):https://edu.csdn.net/course/play/24458/296244?utm_source=blogtoedu
粘包現(xiàn)象解決(終極版)
?
1.簡(jiǎn)單版的問題所在
?
1)報(bào)頭信息不一定只是包含著命令執(zhí)行結(jié)果的字節(jié)數(shù)長(zhǎng)度,在文件傳輸?shù)臅r(shí)候也可能包含文件名等,這時(shí)候就需要用到字典來將文件的相關(guān)信息進(jìn)行封裝
?
2)struct模塊中struct.pack('l',數(shù)據(jù)長(zhǎng)度),這個(gè)數(shù)據(jù)長(zhǎng)度是有限制的,當(dāng)發(fā)送的文件的字節(jié)數(shù)長(zhǎng)度超過時(shí),就會(huì)出現(xiàn)錯(cuò)誤!
?
?
2.知識(shí)點(diǎn)
?
1)字典轉(zhuǎn)為bytes類型:首先使用json.dumps(dict)將字典序列化為json字符串,然后使用.encode('utf-8')對(duì)json字符串進(jìn)行編碼成bytes類型
?
2)bytes類型解析為字典:首先對(duì)bytes進(jìn)行解碼成json字符串,然后將json字符串反序列為字典即可(json.loads(json字符串))
?
3.關(guān)鍵代碼
''' 服務(wù)端 '''......#2處理命令,執(zhí)行命令并且獲得命令得到的結(jié)果obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,#將正確運(yùn)行命令得到的結(jié)果傳給管道stdout中stderr=subprocess.PIPE)#將沒有正確運(yùn)行命令得到的返回信息存放在stderr管道中stdout = obj.stdout.read()stderr = obj.stderr.read()total_size = len(stderr + stdout)#1)制作包含文件名和文件大小的文件頭,用字典實(shí)現(xiàn)headers_dict = {"filename":"nianbao","filedata":"2020/03/09","total_size":total_size}#2)將字典先序列化成驚悚字符串,再轉(zhuǎn)為bytes類型文件頭headers_json = json.dumps(headers_dict)#3)獲取bytes類型的長(zhǎng)度headers_bytes = headers_json.encode('utf-8')headers_size = len(headers_bytes)#4)將bytes類型文件頭長(zhǎng)度定制為固定長(zhǎng)度的報(bào)頭header = struct.pack('i',headers_size)#5)向客戶端發(fā)送報(bào)頭conn.send(header)#6)向客戶端發(fā)送包含文件信息的字典conn.send(headers_bytes)#7)向客戶端發(fā)送真實(shí)命令執(zhí)行的結(jié)果data = stdout + stderrconn.send(data)...... ''' 客戶端 '''......#4、接收服務(wù)器返回來的數(shù)據(jù)recv()#1)先接收由服務(wù)器返回來的報(bào)頭,報(bào)頭是固定長(zhǎng)度的,因此取前面4字節(jié)的數(shù)據(jù)即為報(bào)頭header = phone.recv(4)#返回的是一個(gè)對(duì)象#2)解析報(bào)頭,得到bytes類型的文件頭長(zhǎng)度obj_truple = struct.unpack('i',header)#返回的是一個(gè)元組headers_bytes_size = obj_truple[0]#取元組第一個(gè)元素即為總字節(jié)數(shù)#3)接收bytes類型的文件頭數(shù)據(jù)headers_bytes = phone.recv(headers_bytes_size)#4)將bytes類型的文件頭數(shù)據(jù)反序列化成字典headers_json = headers_bytes.decode('utf-8')headers_dict = json.loads(headers_json)#5)從字典中取出字命令執(zhí)行結(jié)果字節(jié)總長(zhǎng)度total_size = headers_dict['total_size']#6)接收返回的數(shù)據(jù)recv_size = 0data = b''while recv_size < total_size:recv_data = phone.recv(1024)#接收小于1024bytes的數(shù)據(jù)recv_size += len(recv_data)data += recv_data#7)打印字典并且打印返回的數(shù)據(jù)print(headers_dict)print('服務(wù)器返回來的數(shù)據(jù):',data.decode('gbk'))print('*'*50)......4.完整代碼:在上一篇筆記的基礎(chǔ)上修改一下即可
總結(jié)
以上是生活随笔為你收集整理的学习笔记(13):Python网络编程并发编程-解决粘包问题-终极版本的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网站公共部分的复用
- 下一篇: 学习笔记(14):Python网络编程并