IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> python中黏包问题的解决 -> 正文阅读

[网络协议]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()
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-12 17:02:28  更:2021-08-12 17:03:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:30:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码