python網路程式設計之粘包

2022-05-28 21:33:21 字數 4840 閱讀 8448

一、什麼是粘包

須知:只有tcp有粘包現象,udp永遠不會粘包

粘包不一定會發生

如果發生了:1.可能是在客戶端已經粘了

2.客戶端沒有粘,可能是在服務端粘了

首先需要掌握乙個socket收發訊息的原理

應用程式所看到的資料是乙個整體,或說是乙個流(stream),一條訊息有多少位元組對應用程式是不可見的,因此tcp協議是面向流的協議,這也是容易出現粘包問題的原因。(因為tcp是流式協議,不知道啥時候開始,啥時候結束)。而udp是面向訊息的協議,每個udp段都是一條訊息,應用程式必須以訊息為單位提取資料,不能一次提取任意位元組的資料,這一點和tcp是很不同的。怎樣定義訊息呢?可以認為對方一次性write/send的資料為乙個訊息,需要明白的是當對方send一條資訊的時候,無論底層怎樣分段分片,tcp協議層會把構成整條訊息的資料段排序完成後才呈現在核心緩衝區。

所謂粘包問題主要還是因為接收方不知道訊息之間的界限,不知道一次性提取多少位元組的資料所造成的。

二、發生粘包的兩種情況

傳送端需要等緩衝區滿才傳送出去,造成粘包(傳送資料時間間隔很短,資料了很小,會當做乙個包發出去,產生粘包)

from socket import *

2 phone = socket(af_inet,sock_stream)

3 phone.setsockopt(sol_socket,sock_stream,1)

4 phone.bind(('127.0.0.1',8080))

5 phone.listen(5)

6 print('start running...')

7 8 coon,addr = phone.accept() #等待連線

9 10 data1 = coon.recv(10)

11 data2 = coon.recv(10)

12 13 print('------------>',data1.decode('utf-8'))

14 print('------------>',data2.decode('utf-8'))

15 coon.close()

16 phone.close()

from socket import *

2 import time

3 phone = socket(af_inet,sock_stream)

4 phone.connect(('127.0.0.1',8080))

5 6 phone.send('hello'.encode('utf-8'))

7 phone.send('helloworld'.encode('utf-8'))

8 phone.close()

接收方不及時接收緩衝區的包,造成多個包接收(客戶端傳送了一段資料,服務端只收了一小部分,服務端下次再收的時候還是從緩衝區拿上次遺留的資料,產生粘包)

from socket import *

2 phone = socket(af_inet,sock_stream)

3 phone.setsockopt(sol_socket,sock_stream,1)

4 phone.bind(('127.0.0.1',8080))

5 phone.listen(5)

6 print('start running...')

7 8 coon,addr = phone.accept() #等待連線

9 10 data1 = coon.recv(2) #一次沒有接收完整

11 data2 = coon.recv(10) #下一次接收的時候會先取舊的資料,然後取新的

12 # data3 = coon.recv(1024) #接收等5秒後的資訊

13 print('------------>',data1.decode('utf-8'))

14 print('------------>',data2.decode('utf-8'))

15 # print('------------>',data3.decode('utf-8'))

16 coon.close()

17 phone.close()

from socket import *

2 import time

3 phone = socket(af_inet,sock_stream)

4 phone.connect(('127.0.0.1',8080))

5 6 phone.send('hello'.encode('utf-8'))

7 time.sleep(5)

8 phone.send('haiyan'.encode('utf-8'))

9 phone.close()

三、解決粘包的方法問題的根源在於,接收端不知道傳送端將要傳送的位元組流的長度,所以解決粘包的方法就是圍繞,如何讓傳送端在傳送資料前,把自己將要傳送的位元組流總大小讓接收端知曉,然後接收端來乙個死迴圈接收完所有資料

import socket

2 import subprocess

3 import struct

4 phone = socket.socket(socket.af_inet,socket.sock_stream) #買手機

5 phone.bind(('127.0.0.1',8080)) #繫結手機卡

6 phone.listen(5) #阻塞的最大數

7 print('start runing.....')

8 while true: #鏈結迴圈

9 coon,addr = phone.accept()# 等待接**

10 print(coon,addr)

11 while true: #通訊迴圈

12 # 收發訊息

13 cmd = coon.recv(1024) #接收的最大數

14 print('接收的是:%s'%cmd.decode('utf-8'))

15 #處理過程

16 res = subprocess.popen(cmd.decode('utf-8'),shell = true,

17 stdout=subprocess.pipe, #標準輸出

18 stderr=subprocess.pipe #標準錯誤

19 )

20 stdout = res.stdout.read()

21 stderr = res.stderr.read()

22 #先發報頭(轉成固定長度的bytes型別,那麼怎麼轉呢?就用到了struct模組)

23 #len(stdout) + len(stderr)#統計資料的長度

24 header = struct.pack('i',len(stdout)+len(stderr))#製作報頭

25 coon.send(header)

26 #再發命令的結果

27 coon.send(stdout)

28 coon.send(stderr)

29 coon.close()

30 phone.close()

import socket

2 import struct

3 phone = socket.socket(socket.af_inet,socket.sock_stream)

4 phone.connect(('127.0.0.1',8080)) #連線服

5 while true:

6 # 發收訊息

7 cmd = input('請你輸入命令》:').strip()

8 if not cmd:continue

9 phone.send(cmd.encode('utf-8')) #傳送

10 #先收報頭

11 header_struct = phone.recv(4) #收四個

12 unpack_res = struct.unpack('i',header_struct)

13 total_size = unpack_res[0] #總長度

14 #後收資料

15 recv_size = 0

16 total_data=b''

17 while recv_size五、struct模組

#該模組可以把乙個型別,如數字,轉成固定長度的bytes型別

2 import struct

3 res = struct.pack('i',12345)

4 print(res,len(res),type(res)) #長度是4

5 6 res2 = struct.pack('i',12345111)

7 print(res,len(res),type(res2)) #長度也是4

8 9 unpack_res =struct.unpack('i',res2)

10 print(unpack_res) #(12345111,)

11 print(unpack_res[0]) #12345111

python 網路程式設計 02 粘包

思考 什麼是粘包?同時執行多條命令之後,得到的結果很可能只有一部分,在執行其他命令的時候又接收到之前執行的另外一部分結果,這種顯現就是粘包。例如 send b 123 send b abc recv 4 1234 應該接收123 recv 4 bc 應該接收abc或者傳送的資料量大,一次沒有接收完,...

網路程式設計 粘包

粘包問題的產生 tcp流式協議 基於資料流的協議 接收方產生粘包問題 1.接收方不清楚資料有多長只接收了資料的一部分 2.接收方多讀取了資料 傳送方產生的粘包問題 作業系統沒有及時傳送前一次的資料,導致兩次資料粘在一起 粘包問題的根本原因是接收方不清楚資料的長度 tcp nigle 優化機制 如果多...

網路程式設計的粘包

客戶端粘包 傳送端需要等緩衝區滿才傳送出去,造成粘包 傳送資料時間間隔很短,資料量很小,tcp優化演算法會當做乙個包發出去,產生粘包 服務端粘包 接收方不及時接收緩衝區的包,造成多個包接收 客戶端傳送了一段資料,服務端只收了一小部分,服務端下次再收的時候還是從緩衝區拿上次遺留的資料,產生粘包 所謂粘...