python中黏包问题的解决

python中黏包问题的解决

1.在前面我们知道tcp容易产生黏包的问题,而udp不会产生黏包的问题,但是会产生丢包的问题,tcp应用的场景很多所以黏包问题必须要解决。
1.解决黏包问题第一种方法,我们知道黏包问题是由于tcp的优化算法将两个不太大的数据包合并了一起发送的,这种情况一般出现在连续使用几个send()出现的,所以我们如果知道要发送的数据有多大我们就可以设置接收的大小,这样就可以刚好能把所有的数据接收完。下面是具体的步骤细节见代码
这是远程执行cmd命令并返回结果的程序
server端代码
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()
while True:
    cmd = input('>>>')
    conn.send(bytes(cmd,encoding='utf-8'))
    num = conn.recv(1024).decode('utf-8')   #接收client端计算好的数据长度
    conn.send(bytes('ok',encoding='utf-8'))
    #发送一个确认防止发送num的时候跟后面的send内容合并了
    ret = conn.recv(num)
    print(ret.decode('gbk'))
conn.close()
sk.close()

client端代码
import socket
import struct
import subprocess
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:
    cmd = sk.recv(1024).decode('utf-8')
    ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    std_out = ret.stdout.read()
    std_err = ret.stderr.read()
    sk.send(bytes(str(len(std_err)+len(std_out)),encoding='utf-8'))
    #上面计算字符串的长度发送给server端在接收的时候刚好接收那么长的数据
    sk.recv(1024) #ok  这一步主要的目的是为了将num的发送跟后面的send分割开防止黏包现象
    sk.send(std_out)
    sk.send(std_err)
sk.close()
总结这种解决数据的黏包现象有一个问题是多了一次连接延时要接收一个没有用的数据 ok,如何不需要接收ok就能解决黏包现象呢?这就需要下面这种解决方案
2.用struct模块解决黏包现象
server端代码

#tcp黏包现象的解决 struct
import struct
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn,addr = sk.accept()
while True:
    cmd = input('>>>')
    conn.send(bytes(cmd,encoding='utf-8'))
    # num = conn.recv(1024).decode('utf-8')
    num = conn.recv(1024)   #接收数据
    num = struct.unpack('i',num)[0]#进行解包,解包的结果是一个元组类型取第一个数据
    # conn.send(bytes('ok',encoding='utf-8'))
    ret = conn.recv(num)
    print(ret.decode('gbk'))
conn.close()
sk.close()
client端代码

import socket
import struct
import subprocess
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
while True:
    cmd = sk.recv(1024).decode('utf-8')
    ret = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    std_out = ret.stdout.read()
    std_err = ret.stderr.read()
    # sk.send(bytes(str(len(std_err)+len(std_out)),encoding='utf-8'))
    num = len(std_err) + len(std_out)
    num = struct.pack('i',num)  #利用struct模块将一个数据转换成bytes类型 i代表int型
    sk.send(num)
    # sk.recv(1024) #ok
    sk.send(std_out)
    sk.send(std_err)
sk.close()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值