我們使用tcp協議的時候有時會出現一些問題,
就比如我同時傳送了3次資料,但是在另外一邊缺只收到了一次,它把三次資料都和在了一起,
importsocket
server =socket.socket()
server.bind((
'127.0.0.1
',18080)) #
繫結ip和埠
server.listen(2) #
半連線池
conn,addr = server.accept() #
等別人來
data = conn.recv(1024) #
如果conn 沒了,就會報錯
print('
第一次接收--')
print(data.decode('
utf-8'))
data = conn.recv(1024) #
如果conn 沒了,就會報錯
print('
第二次接收---')
print(data.decode('
utf-8'))
data = conn.recv(1024) #
如果conn 沒了,就會報錯
print('
第三次接收---')
print(data.decode('
utf-8
'))
importsocket
client =socket.socket()
client.connect((
'127.0.0.1
',18080)) #
連線client.send(b'11
') #
傳送第一次
client.send(b'
22') #
第二次傳送
client.send(b'
33') #
第三次傳送
>>>第一次接收--
112233第二次接收---第三次接收---
這個就是tcp粘包問題
解決這個問題的關鍵就是設定recv的長度,recv就是獲取資料的長度,所以我們需要得到被傳送資料的長度,但是我們又有可能不知道資料長度的長度,除非我們能固定這個資料的長度。這裡我們可以引入乙個模組:他就能固定資料的長度
struct 模組#對資料進行打包處理,被打包後的資料是固定長度,,我們只需要接收這個固定長度就好,然後把這個包解開,就能得到真正的資料的長度
pack #
打包資料
unpack #
解包資料
這時我們就不止能傳送資料了,還可以把資料的資料資訊(名稱,資料長度,大小),都打包到乙個字典當中,我們直接把字典序列化,然後把字典的報頭(資料長度),和字典一起傳過去就好了。
服務端(傳送)1:生成乙個字典
2:製作字典的報頭
json序列化
編碼統計長度
3:傳送字典的報頭
4:傳送字典
5:傳送真實的資料
客戶端(接收):
1:先接受固定長度,4個位元組的報頭(幾個位元組取決於struct打包的報頭長度)
2:解析獲取的字典資料長度
unpack(...)[0]
3:接受字典資料
解碼反序列化
4:接收真實資料
這樣一來我們就成功解決了粘包問題
importsocket
import
struct
import
json
client =socket.socket()
client.connect((
'127.0.0.1
',8080))
while
true:
msg = input('
>>>:
').encode('
utf-8')
if len(msg) ==0:
continue
client.send(msg)
#1.先接受字典報頭
header_dict = client.recv(4)
#2.解析報頭 獲取字典的長度
dict_size = struct.unpack('
i',header_dict)[0] #
解包的時候一定要加上索引0
#3.接收字典資料
dict_bytes =client.recv(dict_size)
dict_json = json.loads(dict_bytes.decode('
utf-8'))
#4.從字典中獲取資訊
print(dict_json) #
這個是字典
recv_size = 0 #
real_data = b''##
如果一直加這個資料的花,這個資料如果很大,會不會把記憶體弄**?
while recv_size < dict_json.get('
file_size
'): #
如果已經接受的資料總量不大於被接受資料的總量時,跳出迴圈(接收迴圈)
#while recv_size < dict_json.['file_size']: # 不推薦用這個方法,最好用get,這個可能會報錯
data = client.recv(1024) #
一次性接收多大
real_data += data #
把資料加上去
recv_size += len(data) #
print(real_data.decode('
gbk')) #
importsocket
import
subprocess
import
struct
import
json
server =socket.socket()
server.bind((
'127.0.0.1
', 8080))
server.listen(5)
while
true:
conn, addr =server.accept()
while
true:
try:
cmd = conn.recv(1024)
if len(cmd) == 0: break
cmd = cmd.decode('
utf-8')
obj = subprocess.popen(cmd, shell=true, stdout=subprocess.pipe, stderr=subprocess.pipe)
res = obj.stdout.read() +obj.stderr.read()
d = #
這個是檔案大小
#d =
json_d = json.dumps(d) #
格式化#
1.先製作乙個字典的報頭
header = struct.pack('i'
, len(json_d))
print(header,'
---'
,len(header))
#2.傳送字典報頭
conn.send(header) #
傳送字典的檔案大小
#3.傳送字典
conn.send(json_d.encode('
utf-8
')) #
傳送字典
#4.再發真實資料
conn.send(res)
#conn.send(obj.stdout.read())
#conn.send(obj.stderr.read())
except
connectionreseterror:
break
conn.close()
Python網路程式設計,粘包 分包問題的解決
tcp程式設計中的粘包 分包問題的解決 參考 服務端 bin env python coding utf 8 import socket import time import struct import json import socket import sys class sockpackbody...
python 網路程式設計 02 粘包
思考 什麼是粘包?同時執行多條命令之後,得到的結果很可能只有一部分,在執行其他命令的時候又接收到之前執行的另外一部分結果,這種顯現就是粘包。例如 send b 123 send b abc recv 4 1234 應該接收123 recv 4 bc 應該接收abc或者傳送的資料量大,一次沒有接收完,...
python網路程式設計之粘包
一 什麼是粘包 須知 只有tcp有粘包現象,udp永遠不會粘包 粘包不一定會發生 如果發生了 1.可能是在客戶端已經粘了 2.客戶端沒有粘,可能是在服務端粘了 首先需要掌握乙個socket收發訊息的原理 應用程式所看到的資料是乙個整體,或說是乙個流 stream 一條訊息有多少位元組對應用程式是不可...