struct解决socket黏包问题 (指令传输)
服务端代码如下
import struct
import subprocess
import socket
server = socket.socket()
server.bind(('127.0.0.1',))
server.listen()
coon,addr = server.accept()
cmd = coon.recv().decode('utf8')
obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
obj1 = obj.stdout.read()
obj2 = obj.stderr.read()
len_obj = len(obj1+obj2)
len_obj = struct.pack('i',len_obj)
coon.send(len_obj)
coon.send(obj1+obj2)
coon.close()
server.close()
客户端代码
import struct
import socket
client = socket.socket()
client.connect(('127.0.0.1',8900))
cmd = input('>>>')
client.send(cmd.encode('utf8'))
form_server_len = client.recv(4)
print(form_server_len)
form_server_len = struct.unpack('i',form_server_len)[0]
print(form_server_len)
read_len = b''
while len(read_len) < form_server_len:
data = client.recv(1024)
read_len += data
print(read_len.decode('gbk'))
client.close()

每次发送总数据时,要提前将总数据的字节数发过去.
b1 = b'fjdklsfjdsklfjdslfdljskfa' 总长度为:6000个字节 len(b1) = 6000int的字节数
b2 = b'fdisfkljdsjafkl' 总长度为:400个字节 len(b2) = 400 int的字节数
int类型不能直接发送 你要将不同长度的数字类型转化成bytes
6000 ----> str(6000) ----> bytes(6000) b'6000'
此数据的构成: | 数据的总字节数(b'6000')| 具体数据
send(b'6000')
send(b'fjdklsfjdsklfjdslfdljskfa')
由于粘包现象,两次send可能会结合成一个数据发送:
b'6000fjdklsfjdsklfjdslfdljskfa
len(b'6000') 4个字节
recv(4) ---> b'6000'
剩下的6000个字节的数据我要循环recv() b'fjdklsfjdsklfjdslfdljskfa'
你面临的问题: 要将不固定长度的int 转化成固定长度的bytes 利用struct模块
# ret = struct.pack('i',6000)
# print(ret,type(ret),len(ret)) # 固定长度的bytes 4个字节 'b\xe5\x2c\xe1\xe7\'
此数据的构成: | 数据的总字节数(b'6000') (固定长度 4个字节)| 具体数据
send(ret)
send(b'fjdklsfjdsklfjdslfdljskfa')
由于粘包现象,两次send可能会结合成一个数据发送:
b'6000fjdklsfjdsklfjdslfdljskfa
len(b'6000') 4个字节
recv(4) ---> ret 根据struct反解出ret
# w = struct.unpack('i',ret)[0]
# w = 6000 int类型
total_data = b''
while len(total_data) < w:
data = conn.recv(1024)
total_data += data
struct解决socket黏包问题 (指令传输)的更多相关文章
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- 解决Socket粘包问题——C#代码
解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
- struct 模块解决 TCP黏包问题
首先来看一下产生黏包现象的一段代码: # server.py 服务端 import socket sk = socket.socket() sk.bind(('127.0.0.1',9000)) ...
- 解决socket粘包的两种low版模式 os.popen()和struct模块
os.popen()模式 server端 import socket import os phone = socket.socket() # 实例化一个socket对象 phone.bind((&qu ...
- day 24 socket 黏包
socket 套接字的使用: tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 server 端 import socket sk = socket.socket() # 实例化一个 ...
- python学习之socket&黏包
7.4 socket [重要] 避免学习各层的接口,以及协议的使用, socket已经封装好了所有的接口,直接使用这些接口或者方法即可,方便快捷,提升开发效率. socket在python中就是一 ...
- 通过大量实战案例分解Netty中是如何解决拆包黏包问题的?
TCP传输协议是基于数据流传输的,而基于流化的数据是没有界限的,当客户端向服务端发送数据时,可能会把一个完整的数据报文拆分成多个小报文进行发送,也可能将多个报文合并成一个大报文进行发送. 在这样的情况 ...
- 网络编程基础【day09】:解决socket粘包之大数据(七)
本节内容 概述 linux下运行效果 sleep解决粘包 服务端插入交互解决粘包问题 一.概述 刚刚我们在window的操作系统上,很完美的解决了,大数据量的数据传输出现的问题,但是在Linux环境下 ...
- Python之黏包的解决
黏包的解决方案 发生黏包主要是因为接收者不知道发送者发送内容的长度,因为tcp协议是根据数据流的,计算机操作系统有缓存机制, 所以当出现连续发送或连续接收的时候,发送的长度和接收的长度不匹配的情况下就 ...
随机推荐
- Java模拟HttpClient进行Get和Post提交
使用Java模拟客户端进行提交,需要用到apache http client jar,这里用的是4.4版本 GET: public void GetURL(){ String strResp=&qu ...
- jq轮播图实现
html基本框架如下: <div class="out"> <ul class="img"> <li><a href= ...
- Vue小白篇 -Vue 的模板语法
可以插入任何你想插入的内容,除了 if-else if-else用三元运算符代替 <div id="box"> <!--模板语法--> <h2> ...
- curl分析请求的各个部分耗时情况
curl 命令提供了 -w 参数,解释如下 -w, --write-out Make curl display information on stdout after a completed tran ...
- 初识localstorage用法
最近在做一个类似填报信息的页面,一共有8页,当点击切换到下一页的时候要求把上一页的数据存到本地,以便下次切换到这个页面的时候自动把值填上去,并且在最后一页提交数据的时候直接用localstorage里 ...
- 76 学习C++
0 引言 C++语言特性记录,提高对这门语言的理解,进而带动对编程语言特性的理解. 相关网站及教程 # W3Cschool C++教程 https://www.w3cschool.cn/cpp/ # ...
- paper 134:结构张量structure tensor(二)
根据结构张量能区分图像的平坦区域.边缘区域与角点区域. 此算法也算是计算机科学最重要的32个算法之一了.链接的文章中此算法名称为Strukturtensor算法,不过我搜索了一下,Strukturte ...
- AcWing 243. 一个简单的整数问题2 (树状数组)打卡
题目:https://www.acwing.com/problem/content/244/ 题意:区间加,区间查询 思路:我们把原先那个差分数组分解一下 ∑i=1x∑j=1ib[j]=∑i=1x(x ...
- 埋坑一: vue中子组件调用兄弟组件方法
小计: 开发中遇到子组件需要调用兄弟组件中的方法,如下写个小demo记录下心得,如果你有好的方法,请到评论区域指教 父组件示例代码: 组件功能解析: 通过$emit获取子组件事件,通过$ref调用子组 ...
- 没有找到MSVCR110.dll,因此这个应用程序未能启动.重新安装应用程序可能会修复此问题
问题: 在win7下用vs2012编译了一个exe放到xp上运行,弹出错误框"没有找到MSVCR110.dll,因此这个应用程序未能启动.重新安装应用程序可能会修复此问题" 解决办 ...