一、粘包问题

问题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粘包问题及解决方案的更多相关文章

  1. Socket粘包问题终极解决方案—Netty版(2W字)!

    上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...

  2. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  3. Python socket粘包解决

    socket粘包: socket 交互send时,连续处理多个send时会出现粘包,soket会把两条send作为一条send强制发送,会粘在一起. send发送会根据recv定义的数值发送一个固定的 ...

  4. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  5. socket粘包现象加解决办法

    socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...

  6. Socket粘包问题

    这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...

  7. C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)

    介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...

  8. [转]关于Socket粘包问题

    这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...

  9. 解决Socket粘包问题——C#代码

    解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...

随机推荐

  1. 前后端登录注册之node剖析与token的使用状态

    登录模块功能详解 1.用户名密码的格式验证 由前端完成,根据需求自行决定,不加叙述 2.点击提交按钮思路详解 前端将用户名 以及加密后的密码还有验证码输入的内容统一发给后端  由后端和数据库的数据进行 ...

  2. 错误处理——According to TLD or attribute directive in tag file, attribute test does not accept any expres

    应用部署运行的时候出现JSP异常, 发生在使用JSTL库的时候: According to TLD or attribute directive in tag file, attribute valu ...

  3. oracle函数 LENGTH(c1)

    [功能]返回字符串的长度; [说明]多字节符(汉字.全角符等),按1个字符计算 [参数]C1 字符串 [返回]数值型 [示例] SQL> select length('高乾竞'),length( ...

  4. 深入python

    while循环知识: while是关键字 格式我们要怎么写:; while 条件 : 缩进    循环(代码块) 这里面有个死循环######条件如果一直为真,就形成了一个环,就成为了死循环 那我们如 ...

  5. H3C 用debugging ppp all命令调试PPP

  6. 解决 npm run dev b报错 “'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序 或批处理文件。”

    摘自:https://www.cnblogs.com/laraLee/p/9174383.html 前提: 电脑已经安装了nodeJS和npm,  项目是直接下载的zip包. 在项目目录下运行“npm ...

  7. JDK自带的native2ascii工具介绍

    背景:在做Java开发的时候,常常会出现一些乱码,或者无法正确识别或读取的文件,比如常见的validator验证用的消息资源(properties)文件就需要进行Unicode重新编码.原因是java ...

  8. ASP.NET MVC4.0+EF+LINQ+bui+bootstrap+网站+角色权限管理系统(开篇)

    系统预览: 源码下载:http://www.yealuo.com/Home/Detail?KeyValue=2f926407-f80b-4bff-a729-949a53efed7b 创建项目,新手按步 ...

  9. 深浅Copy的理解

    在python里对对象进行拷贝有三个,即赋值,深拷贝,浅拷贝. 而对象又分为两种,一种是不可变对象(字符串.元组.数字 ),一种是可变对象(列表.字典). 而深浅拷贝有三种情况:拷贝的是不可变对象.拷 ...

  10. PowerShell 通过 WMI 获取系统服务

    本文告诉大家如何通过 WMI 获取系统服务 通过 Win32_Service 可以获取系统启动的服务 Get-WmiObject Win32_Service | Format-List Caption ...