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发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
随机推荐
- cume_dist(),名次分析——-最大排名/总个数
函数:cume_dist() over(order by id) select id,area,score, cume_dist() over(order by id) a, --按ID最大排名/总个 ...
- P2P需集齐四大证照
今后做P2P需集齐四大证照 比牌照制还严 2016-09-05 11:53:24 分类:热点观察 作者:汪祖刚 8月24日,P2P网贷监管细则在千呼万唤中始出来,整个行业内外的关注热度可谓史无前例.有 ...
- HZOJ 礼物
其实是比较简单的一道期望状压dp,考试时一直在想数组表示概率,然而最后出的数总是小于一,于是无奈的把第一个点判掉放弃了其他点. 设f[i]为状态为i时到全部买到的期望次数,$f[i]=∑f[j]*p[ ...
- mysql查同个实例两个数据库中的表名差异
select TABLE_NAME from ( select TABLE_NAME ,) as cnt from information_schema.tables where TABLE_SCHE ...
- Jupyter Magic - Timing(%%time %time %timeit)
对于计时有两个十分有用的魔法命令:%%time 和 %timeit. 如果你有些代码运行地十分缓慢,而你想确定是否问题出在这里,这两个命令将会非常方便. 1.%%time 将会给出cell的代码运行一 ...
- [转]安卓加固之so文件加固
一.前言 最近在学习安卓加固方面的知识,看到了jiangwei212的博客,其中有对so文件加固的两篇文章通过节加密函数和通过hash段找到函数地址直接加密函数,感觉写的特别好,然后自己动手实践探索s ...
- 【CSS3】loading动画
HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- 2019-6-23-win10-uwp-解决-SerialDevice.FromIdAsync-返回空
title author date CreateTime categories win10 uwp 解决 SerialDevice.FromIdAsync 返回空 lindexi 2019-6-23 ...
- Nutch2.3 编译
$ antBuildfile: build.xmlTrying to override old definition of task javac ivy-probe-antlib: ivy-downl ...
- React 蚂蚁金服+ Antd 组件使用技巧
安装antd 组件 yarn add antd -D import { Card,Button,Table,From,Modal ,Select } from 'antd'; .引入就可以使用了 ...