码迷,mamicode.com
首页 > 其他好文 > 详细

解决粘包

时间:2020-05-02 14:45:49      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:enc   消息   指令   opened   splay   str   lap   cep   res   

两种粘包现象
    1 连续的小包可能会被优化算法给组合到一起进行发送
    2 第一层次如果发送的数据大小为2000B,接收端一次性接受大小为1024B,这就导致剩下的内容会被下一次recv接收到,导致混乱
解决方案一.
    由于双方不知道对方发送数据的长度,导致接收的时候,可能接收不全,或者多接收另外一次
    发送的信息内容,所以在发送真是数据之前,要先发送数据的长度,接收端根据长度来接收后面
    的真实数据。
技术图片
import socket
import subprocess
server = socket.socket()
ip_port = (127.0.0.1,8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
    from_client_cmd = conn.recv(1024)
    print(from_client_cmd.decode(utf-8))
    #接收到客户端发送来的系统指令,我服务端通过subprocess模块到服务端自己的系统里面执行这条指令
    sub_obj = subprocess.Popen(
        from_client_cmd.decode(utf-8),
        shell=True,
        stdout=subprocess.PIPE,  #正确结果的存放位置
        stderr=subprocess.PIPE   #错误结果的存放位置
    )
    #从管道里面拿出结果,通过subprocess.Popen的实例化对象.stdout.read()方法来获取管道中的结果
    std_msg = sub_obj.stdout.read()
 
    #为了解决黏包现象,我们统计了一下消息的长度,先将消息的长度发送给客户端,客户端通过这个长度来接收后面我们要发送的真实数据
    std_msg_len = len(std_msg)
    # std_bytes_len = bytes(str(len(std_msg)),encoding=‘utf-8‘)
    #首先将数据长度的数据类型转换为bytes类型
    std_bytes_len = str(len(std_msg)).encode(utf-8)
    print(指令的执行结果长度>>>>,len(std_msg))
    conn.send(std_bytes_len)
 
    status = conn.recv(1024)
    if status.decode(utf-8) == ok:
        conn.send(std_msg)
    else:
        pass
View Code
技术图片
import socket
 
client = socket.socket()
client.connect((127.0.0.1,8001))
while 1:
    cmd = input(请输入指令:)
    client.send(cmd.encode(utf-8))
    server_res_len = client.recv(1024).decode(utf-8)
    print(来自服务端的消息长度,server_res_len)
    client.send(bok)
    server_cmd_result = client.recv(int(server_res_len))
    print(server_cmd_result.decode(gbk))
View Code
解决方案二:使用struct模块处理数据长度,再将发送的数据长度和内容整合在一起发送
    struct模块封装的int类型为4个字节,所以可以直接在接收时先定下长度.
    打包:struct.pack(‘i‘,长度)
    解包:struct.unpack(‘i‘,字节流)

  

技术图片
import socket
import subprocess
import struct
server = socket.socket()
ip_port = (127.0.0.1,8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
 
while 1:
    from_client_cmd = conn.recv(1024)
 
    print(from_client_cmd.decode(utf-8))
    #接收到客户端发送来的系统指令,我服务端通过subprocess模块到服务端自己的系统里面执行这条指令
    sub_obj = subprocess.Popen(
        from_client_cmd.decode(utf-8),
        shell=True,
        stdout=subprocess.PIPE,  #正确结果的存放位置
        stderr=subprocess.PIPE   #错误结果的存放位置
    )
    #从管道里面拿出结果,通过subprocess.Popen的实例化对象.stdout.read()方法来获取管道中的结果
    std_msg = sub_obj.stdout.read()
 
    #为了解决黏包现象,我们统计了一下消息的长度,先将消息的长度发送给客户端,客户端通过这个长度来接收后面我们要发送的真实数据
    std_msg_len = len(std_msg)
 
    print(指令的执行结果长度>>>>,len(std_msg))
 
    msg_lenint_struct = struct.pack(i,std_msg_len)
    conn.send(msg_lenint_struct+std_msg) 
View Code
技术图片
import socket
import struct
client = socket.socket()
client.connect((127.0.0.1,8001))
 
while 1:
    cmd = input(请输入指令:)
    #发送指令
    client.send(cmd.encode(utf-8))
 
    #接收数据长度,首先接收4个字节长度的数据,因为这个4个字节是长度
    server_res_len = client.recv(4)
    msg_len = struct.unpack(i,server_res_len)[0]
 
    print(来自服务端的消息长度,msg_len)
    #通过解包出来的长度,来接收后面的真实数据
    server_cmd_result = client.recv(msg_len)
 
    print(server_cmd_result.decode(gbk))
View Code

 

解决粘包

标签:enc   消息   指令   opened   splay   str   lap   cep   res   

原文地址:https://www.cnblogs.com/topass123/p/12817881.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!