python網路程式設計 粘包問題的解決

2022-06-22 08:39:10 字數 4103 閱讀 8416

我們使用tcp協議的時候有時會出現一些問題,

就比如我同時傳送了3次資料,但是在另外一邊缺只收到了一次,它把三次資料都和在了一起,

import

socket

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

'))

import

socket

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:接收真實資料

這樣一來我們就成功解決了粘包問題

import

socket

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')) #

import

socket

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 一條訊息有多少位元組對應用程式是不可...