粘包现象和解决方法

一.缓冲区

  缓冲区:将程序和网络解耦(类似于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)
原文地址:https://www.cnblogs.com/q767498226/p/10225769.html