一、粘包问题

问题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. 洛谷 3174 [HAOI2009]毛毛虫

    题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大.例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 ). 输入输出格 ...

  2. Bitmap的recycle问题

        虽然Android有自己的垃圾回收机制,对于是不是要我们自己调用recycle,还的看情况而定.如果只是使用少量的几张图片,回收与否关系不大.可是若有大量bitmap需要垃圾回收处理,那必然垃 ...

  3. Project Euler Problem 12-Highly divisible triangular number

    最直接的想法就是暴力搞搞,直接枚举,暴力分解因子.再好一点,就打个素数表来分解因子.假设num=p1^a1p2^a2...pn^an,则所有因子个数为(a1+1)(a2+1)...(an+1). 再好 ...

  4. H3C TCP连接的拆除

  5. 2001年NOIP普及组复赛题解

    题目涉及算法: 数的计算:动态规划: 最大公约数和最小公倍数问题:质因数分解: 求先序排列:递归: 装箱问题:动态规划(纯0-1背包问题) 数的计算 题目链接:https://www.luogu.or ...

  6. Python--day66--内容回顾

    3,python中的大小比较和js中的大小比较规则: python中a>b>c,就是先比较a>b,然后再比较b>c,都为true的话就返回true: js中的a>b> ...

  7. dos taskkill 命令

    C:\Users\asn\Desktop>taskkill /? TASKKILL [/S system [/U username [/P [password]]]] { [/FI filter ...

  8. JPA 一对多双向映射 结果对象相互迭代 造成堆栈溢出问题方法

    问题: JPA 在双向映射时,会相互包含对方的实例,相互引用,造成递归迭代,堆栈溢出(java.lang.StackOverflowError). 分析: 在后端向前端传递的时候会将数据序列化,转为j ...

  9. js 页面分享

    首先说分享到QQ空间的通用代码:<a href="javascript:void(0);" onclick="window.open('http://sns.qzo ...

  10. 【React】富文本编辑器 清空文本内容 获取HTML

    富文本编辑器  React  传入 import React,{Component } from 'react'; import { Card, Button, Table, Form, Select ...