网络编程的粘包

粘包处理

客户端粘包:

发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据量很小,TCP优化算法会当做一个包发出去,产生粘包)

服务端粘包

接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包) 

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

解决方法:(发送一个报头告诉对方我要发的有送多大)

先说下连接循环和通信循环

# 服务端  连接循环+通信循环
import scoket
server = socket.socket()
server.bind(('127.0.0.1',8686)) # 本地回环地址 
server.listen(5) # 半连接池  除了正在服务的 还有五个等待连接
while True:
    # 连接循环
    conn, addr = server.accept() # conn 是双向连接通道 套接字的对象 addr是客户端地址
    while True:
        # 通信循环
        try:
            date = conn.recv(1024) # 等待接收1024字节
            ptint(date.decode('utf-8'))
            if len(date) == 0:break
            conn.send(date.upper()) # 返回消息
         except ConnectResetError as c: #连接中断等待下一个连接诶
            print(c)
            break
     conn.close()
    
 # 客户端
import socket 

client = socket.socket()
client.connect(('127.0.0.1',8686))
while True:
	cmd = input(">>>").encode('utf-8')
    client.send(cmd)
    date = client.recv(1024)
    print(date)

TCP的粘包问题

# 服务端
import socket

server = socket.socket()  # 买手机 不传参数默认用的就是TCP协议
server.bind(('127.0.0.1',8080))  # bind((host,port))  插电话卡  绑定ip和端口
server.listen(5)  # 开机    半连接池

conn, addr = server.accept()  # 接听电话  等着别人给你打电话     阻塞
data = conn.recv(5)  # 听别人说话 接收1024个字节数据          阻塞
print(data)
data = conn.recv(5)  # 听别人说话 接收1024个字节数据          阻塞
print(data)
data = conn.recv(4)  # 听别人说话 接收1024个字节数据          阻塞
print(data)

# 服务端
import socket
client = socket.socket()  # 拿电话
client.connect(('127.0.0.1',8080))  # 拨号   写的是对方的ip和port
client.send(b'hello')
client.send(b'world')
client.send(b'baby')

粘包的处理

# 服务端
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 = {'name':'jason','file_size':len(res),'info':'asdhjkshasdad'}
            json_d = json.dumps(d)
            # 1.先制作一个字典的报头
            header = struct.pack('i',len(json_d))
            # 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()
 
# 客户端
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'):  # real_size = 102400
        data = client.recv(1024)
        real_data += data
        recv_size += len(data)
    print(real_data.decode('gbk'))
趁自己还没死 多折腾折腾
原文地址:https://www.cnblogs.com/lddragon/p/11323266.html