1. 程式人生 > >python全棧學習--day35(黏包機制)

python全棧學習--day35(黏包機制)

class 網關 優化方法 OS 方法 xxx mission 多條 lose

黏包

粘包現象

同時執行多條命令之後,得到的結果很可能只有一部分,在執行其他命令的時候又接收到之前執行的另外一部分結果,這種顯現就是黏包。

基於tcp協議實現的粘包

server 端

######server 端
from socket import *
ip_port=(‘127.0.0.1‘,8080)

tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)

conn,addr=tcp_socket_server.accept()

data1=conn.recv(2)
data2=conn.recv(10)

print(‘----->‘,data1.decode(‘utf-8‘))
print(‘----->‘,data2.decode(‘utf-8‘))

conn.close()
tcp_socket_server.close()

  client 端

##########client
#_*_coding:utf-8_*_ import socket BUFSIZE=1024 ip_port=(‘127.0.0.1‘,8080) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) res=s.connect_ex(ip_port) s.send(‘hello‘.encode(‘utf-8‘)) s.send(‘egg‘.encode(‘utf-8‘)) s.close()

  執行輸出:

技術分享圖片

說明:上圖中就是黏包的效應

原理

黏包現象的成因

  #你不知道在哪兒斷句

解決辦法:

  在發送數據的時候,先告訴對方要發送的大小就可以了

  在發送的時候,先發送數據的大小 在發送內容

  在接收的時候,先接受大小,在根據大小接收內容

自動協議

# ret = struct.pack(‘i‘,1920000)
# print(ret)
#
# ret = struct.unpack(‘i‘,ret)
# print(ret[0])

# 能夠把範圍內一個任意的整數轉換成一個固定長度的字節
# 還能轉換回來

# 發送數據的時候
# xxxxtttttttttttttttttttttttttttttt
# 自定義了一個協議

import struct
import socket

sk = socket.socket()
sk.bind((‘127.0.0.1‘,9000))
sk.listen()

conn,addr = sk.accept()
while True:
    ret = conn.recv(4)
    length = struct.unpack(‘i‘,ret)[0]
    msg = conn.recv(length)
    print(msg.decode(‘utf-8‘))
conn.close()

  

import socket
import struct

sk = socket.socket()
sk.connect((‘127.0.0.1‘,9000))
while True:
    msg = ‘hello world‘
    length = struct.pack(‘i‘,len(msg))
    sk.send(length)
    sk.send(msg.encode(‘utf-8‘))
sk.close()

  技術分享圖片

黏包成因

TCP協議中的數據傳遞

tcp協議的拆包機制

當發送端緩沖區的長度大於網卡的MTU時,tcp會將這次發送的數據拆成幾個數據包發送出去。 
MTU是Maximum Transmission Unit的縮寫。意思是網絡上傳送的最大數據包。MTU的單位是字節。 大部分網絡設備的MTU都是1500。如果本機的MTU比網關的MTU大,大的數據包就會被拆開來傳送,這樣會產生很多數據包碎片,增加丟包率,降低網絡速度。

面向流的通信特點和Nagle算法

TCP(transport control protocol,傳輸控制協議)是面向連接的,面向流的,提供高可靠性服務。
收發兩端(客戶端和服務器端)都要有一一成對的socket,因此,發送端為了將多個發往接收端的包,更有效的發到對方,使用了優化方法(Nagle算法),將多次間隔較小且數據量小的數據,合並成一個大的數據塊,然後進行封包。
這樣,接收端,就難於分辨出來了,必須提供科學的拆包機制。 即面向流的通信是無消息保護邊界的。 
對於空消息:tcp是基於數據流的,於是收發的消息不能為空,這就需要在客戶端和服務端都添加空消息的處理機制,防止程序卡住,而udp是基於數據報的,即便是你輸入的是空內容(直接回車),也可以被發送,udp協議會幫你封裝上消息頭發送過去。 
可靠黏包的tcp協議:tcp的協議數據不會丟,沒有收完包,下次接收,會繼續上次繼續接收,己端總是在收到ack時才會清除緩沖區內容。數據是可靠的,但是會粘包。

python全棧學習--day35(黏包機制)