1. 程式人生 > >粘包現象和解決方法

粘包現象和解決方法

一.緩衝區

  緩衝區:將程式和網路解耦(類似於cpu和硬碟需要記憶體來緩衝一樣)

  輸入緩衝區

  輸出緩衝區

二.subprocess和struct模組的簡單認識  

import subprocess

sub_obj = subprocess.Popen(
     "dir",                                       # cmd指令
     shell=True,
    stdout = subprocess.PIPE,           #正確的指令存放位置
    stderr = subprocess.PIPE            # 錯誤的指令存放位置  
)
print(sub_obj.stdout.read().decode("gbk")) # read 拿到的是位元組,需要解碼(需要解碼的位元組是系統預設的)
import struct

a = 10

byt = struct.pack("i",a)  # 將int型別的a打包成4個位元組長度的二進位制

a1 = struct.unpack("i",byt)  # 將byt解包成一個int型別,返回的是一個元組

三.兩種粘包現象(TCP)

  1.連續(傳送資料間隔短)兩個小的資料流會被優化演算法給組合到一起併發送,造成粘包

模擬粘包現象服務端

import socket

server = socket.socket()
ip_port = ("127.0.0.1",8888)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()

from_client_msg1 = conn.recv(1024)
print(from_client_msg1)
from_client_msg2 = conn.recv(1024)
print(from_client_msg2)

模擬粘包現象客戶端

import socket

client = socket.socket()
client.connect(("127.0.0.1",8888))

to_send1 = client.send(b"123")
to_send2 = client.send(b"123")

  2.一個大的資料流過大,超過revc的值,那麼會一次接收不完,暫時存放在緩衝區,下次再接收的時候就會拿到一六的資料,造成粘包

模擬粘包現象服務端

import socket
import subprocess

server = socket.socket()
ip_port = ("127.0.0.1",8888)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
    from_client_cmd = conn.recv(1024).decode("utf-8")   # 一次只能接收1024b 剩下的存在緩衝區 第二次再接收會粘包

    sub_obj = subprocess.Popen(
        from_client_cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    to_client_res = sub_obj.stdout.read()
    print(len(to_client_res))
    conn.send(to_client_res)

模擬粘包現象客戶端

import socket

client = socket.socket()
ip_port = ("127.0.0.1",8888)
client.connect(ip_port)

while 1:
    cmd = input("請輸入cmd指令:").encode("utf-8")         # 輸入ipconfig -all 
    client.send(cmd)

    server_cmd_res = client.recv(1024).decode("gbk")
    print(server_cmd_res)

四.產生粘包的原因及解決方案

  1.產生粘包的原因:接收方不知道訊息之間的界限,不知道一次性提取多少資料造成的

  2.解決粘包現象的方案:自定義一個長度報頭

解決粘包現象服務端

import socket
import subprocess
import struct

server = socket.socket()
ip_port = ("127.0.0.1",8888)
server.bind(ip_port)
server.listen()

conn,addr = server.accept()

while 1:
    from_client_cmd = conn.recv(1024).decode("utf-8")

    sub_obj = subprocess.Popen(
        from_client_cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    # print(sub_obj.stdout.read())
    sub_res = sub_obj.stdout.read()
    cmd_len = len(sub_res)
    cmd_len_byt = struct.pack("i",cmd_len)
    conn.send(cmd_len_byt + sub_res)  

解決粘包現象客戶端

import socket
import struct

client = socket.socket()
client.connect(("127.0.0.1",8888))

while 1:
    cmd = input("請輸入cmd指令:").encode("utf-8")
    client.send(cmd)

    cmd_len_byt = client.recv(4)
    cmd_len = struct.unpack("i",cmd_len_byt)[0]

    cmd_msg = client.recv(cmd_len).decode("gbk")
    print(cmd_msg)