socket粘包问题及解决方案
一、粘包问题
问题1: 无法确认对方发送过来数据的大小。
‘client.py'
import socket
client = socket.socket()
client.connect(
('127.0.0.1', 9000)
)
while True:
cmd = input('客户端输入的内容: ')
client.send(cmd.encode('utf-8'))
data = client.recv(19190)
print(len(data))
print(data.decode('gbk'))
‘server.py'
import socket
import subprocess
server = socket.socket()
server.bind(('127.0.0.1',9000))
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
cmd = conn.recv(10)
if len(cmd) == 0:
continue
cmd = cmd.decode('utf-8') #utf8
if cmd == 'q':
break
#调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
obj = subprocess.Popen(
#cmd接受的是解码后的字符串
cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
#结果交给result变量名
result = obj.stdout.read()+obj.stderr.read()
print(len(result))
print(result.decode('gbk')) #windows系统下默认编码gbk
#将结果返回给客户端
conn.send(result)
except Exception as e:
print(e)
break
conn.close()
问题2: 在发送数据间隔短并且数据量小的情况下,会将所有数据一次性发送。
‘client.py'
import socket
client = socket.socket()
client.connect(
('127.0.0.1', 9000)
)
client.send(b'hello')
client.send(b'hello')
client.send(b'hello')
‘server.py'
import socket
server = socket.socket()
server.bind(
('127.0.0.1', 9000)
)
server.listen(5)
conn, addr = server.accept()
data = conn.recv(5)
print(data) # b'hello'
data = conn.recv(1024)
print(data) # b'hello'
data = conn.recv(1024)
print(data) # b'hello'
二、粘包问题的解决方案:
粘包问题的解决方案: 确认对方数据的大小。
这里需要用 struct模块
struct是什么?
是一个python内置的模块,它可以将固定长度的数据,打包成固定格式的长度。
固定格式:如 “ i ” 模式
i : 4
struct作用:
可以将真实数据,做成一个固定长度的报头,客户端发送给服务器,服务器可以接受报头,然后对报头进行解包,获取真实数据的长度,进行接收即可
import struct
data = b'1111111111111111'
print(len(data)) #16
#打包制作报头
header = struct.pack('i',len(data))
print(header) #b'\x10\x00\x00\x00'
print(len(header)) #4
#解包获取真实数据长度 --->得到一个元组,元组中第一个值是真实数据的长度
res = struct.unpack('i',header)[0]
print(res) #16
无论哪一端先发送数据
客户端
- 1) 先制作报头,并发送 (struct)
- 2) 发送真实数据服务端:
- 1) 接收报头,并解包获取 真实数据长度
- 2) 根据真实数据长度 接收真实数据
recv(真实数据长度)
简单版:
‘client.py'
import socket
import struct
client = socket.socket()
client.connect(('127.0.0.1', 9000))
while True:
cmd = input('客户端输入的内容: ')
cmd_bytes = cmd.encode('utf-8')
header = struct.pack('i',len(cmd_bytes)) #做一个报头
print(len(header)) #打印报头的长度
client.send(header) #发送报头
client.send(cmd_bytes) #待服务端确认长度后,发送真实数据长度
headers = client.recv(4) #接受服务端的报头
data_len = struct.unpack('i',headers)[0] #解包
result = client.recv(data_len) #接受服务器返回的真实数据的长度
print('接受服务器返回的真实数据的长度',len(result))
print(result.decode('gbk'))
‘server.py'
import socket
import subprocess
import struct
server = socket.socket()
server.bind(('127.0.0.1',9000))
server.listen(5)
while True:
conn,addr = server.accept()
print(addr)
while True:
try:
header = conn.recv(10) #获取客户端传过来的报头
data_len = struct.unpack('i',header)[0] #解包获取真实数据的长度
cmd = conn.recv(data_len) #准备接受真实数据
if len(cmd) == 0:
continue
cmd = cmd.decode('utf-8')
if cmd == 'q':
break
#调用subprocess连接终端,对终端进行操作,并获取操作后正确或错误的结果
obj = subprocess.Popen(
#cmd接受的是解码后的字符串
cmd,shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
result = obj.stdout.read()+obj.stderr.read() #获取结果
print('发送给服务端返回的真实数据的长度', len(result))
header = struct.pack('i', len(result)) #做报头
print(len(header))
conn.send(header) #发送报头给客户端
conn.send(result) #将结果返回给客户端
except Exception as e:
print(e)
break
conn.close()
序列化版:
‘client.py'
import socket,json
import struct
client = socket.socket()
client.connect(('127.0.0.1',9000))
while True:
movie_name = input('请输入上传的电影名字:')
#伪装电影的真实数据
movie = 1000000
send_dic ={'movie_name':movie_name,
'movie':movie}
#序列化
json = json.dumps(send_dic)
print(json)
print(json.encode('utf-8'))
print(len(json.encode('utf-8')))
json_bytes = json.encode('utf-8')
#做一个报头
header = struct.pack('i',len(json_bytes))
#先发送报头
client.send(header)
#再发送真实数据
client.send(json_bytes)
‘server.py'
import socket,json
import struct
server = socket.socket()
server.bind(('127.0.0.1',9000))
server.listen(5)
while True:
conn,addr = server.accept()
while True:
try:
#获取客户端传过来的报头
header = conn.recv(4)
#解包获取真实数据的长度
json_len = struct.unpack('i',header)[0]
#接受json(dic)的真实数据
json_bytes_data = conn.recv(json_len)
#将bytes类型数据转为json数据类型
json_data = json_bytes_data.decode('utf-8')
#反序列化 json--->dict
back_dic = json.loads(json_data)
print(back_dic)
print(back_dic.get('movie'))
except Exception as e:
print(e)
break
conn.close()
socket粘包问题及解决方案的更多相关文章
- Socket粘包问题终极解决方案—Netty版(2W字)!
上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...
- UNIX网络编程——tcp流协议产生的粘包问题和解决方案
我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...
- Python socket粘包解决
socket粘包: socket 交互send时,连续处理多个send时会出现粘包,soket会把两条send作为一条send强制发送,会粘在一起. send发送会根据recv定义的数值发送一个固定的 ...
- python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- socket粘包现象加解决办法
socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...
- Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- [转]关于Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- 解决Socket粘包问题——C#代码
解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
随机推荐
- Python 基础06 循环
循环用于重复执行一些程序块.从上一讲的选择结构,我们已经看到了如何用缩进来表示程序块的隶属关系. 循环也会用到类似的写法. for 循环 for 循环需要预先设定好循环的次数(n) 然后执行隶属于fo ...
- 洛谷P1807 最长路_NOI导刊2010提高(07)
//拓扑排序求最长路 #include<bits/stdc++.h> #include<queue> using namespace std; const int INF=0x ...
- centos安装hdp
1. 准备6和7的 YUM源包 1.1 centos 下载后解压到同一个目录 http://mirrors.163.com/centos/6/isos/x86_64/CentOS-6.9-x86_64 ...
- 使用Laravel的队列实现系统通知、
使用Laravel的队列实现系统通知. 第一步:创建 jobs表的migrate php artisan queue:table 第二步:创建jobs 表 php artisan migrate 第三 ...
- SuperSocket命令加载器 (Command Loader)
在某些情况下,你可能希望通过直接的方式来加载命令,而不是通过自动的反射. 如果是这样,你可以实现你自己的命令加载器 (Command Loader): public interface IComman ...
- Python 3.7.0 For Mac版软件安装教程附下载地址
https://www.jianshu.com/p/f02d6f01eba7
- 2019-3-8-win10-uwp-渲染原理-DirectComposition-渲染
title author date CreateTime categories win10 uwp 渲染原理 DirectComposition 渲染 lindexi 2019-03-08 09:18 ...
- H3C 什么是OSPF
- v-for(:key)绑定index、id、key的区别
Vue 2.0 v-for 响应式key, index及item.id参数对v-bind:key值造成差异研究 在github上阅览README.md以获得最佳阅读体验,点这里 v-for响应式key ...
- vue-lazyload: 想弃坑,但没有找到合适的替代品
vue-lazyload,相信在vue项目中大家都有用到过它,同时也遇到过大大小小的坑.笔者也遇到过这样一个bug,在一个图片列表页面中,总有一定的概率图片的状态为load,导致图片一直加载中...这 ...