解决socket粘包的两种low版模式 os.popen()和struct模块
无注释版
os.popen()模式
server端
import socket
import os
phone = socket.socket()
phone.bind(("localhost",8088))
phone.listen()
while 1:
conn,addr = phone.accept()
while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.upper() == b'Q':
print("客户端退出")
break
print(from_client_data.decode('utf-8'))
cmd_res = os.popen(from_client_data.decode("utf-8")).read()
if len(cmd_res) == 0:
cmd_res = "cmd hs no output..."
print(len(cmd_res.encode('gbk')))
conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk'))
client.ack = conn.recv(1024)
conn.send(cmd_res.encode('gbk'))
except ConnectionResetError:
break
conn.close()
phone.close()
client端
import socket
phone = socket.socket()
phone.connect(('localhost',8088))
while 1:
client_data = input(">>>")
if not client_data:
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8"))
if client_data.upper() == "Q":
quit()
else:
server_data = phone.recv(1024)
phone.send("准备好接收了".encode('utf-8'))
total_size = int(server_data.decode('gbk'))
total_data = b''
while 1:
if len(total_data) < total_size:
total_data += phone.recv(1024)
print(len(total_data))
else:
break
print(total_data.decode('gbk'))
phone.close()
struct模块解决粘包
server端
import socket
import subprocess
import struct
phone = socket.socket()
phone.bind(("localhost",8088))
phone.listen(5)
while 1:
conn,addr = phone.accept()
print(addr)
while 1:
try:
from_client_data = conn.recv(1024)
if from_client_data.upper() == b'Q':
print("客户端退出")
break
print(from_client_data.decode('utf-8'))
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)
ret = obj.stdout.read()+obj.stderr.read()
total_size = len(ret)
header = struct.pack('i',total_size)
print(total_size)
conn.send(header)
conn.send(ret)
except ConnectionResetError:
break
conn.close()
phone.close()
client端
import socket
import struct
phone = socket.socket()
phone.connect(('localhost',8088))
while 1:
client_data = input(">>>")
if not client_data:
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8"))
if client_data.upper() == "Q":
quit()
else:
server_data = phone.recv(4)
total_size = struct.unpack('i',server_data)[0]
total_data = b''
while 1:
if len(total_data) < total_size:
total_data += phone.recv(1024)
print(len(total_data))
else:
break
print(total_data.decode('gbk'))
# print(int(server_data.decode('gbk')))
phone.close()
有注释版
os.popen()模式
server端
import socket
import os
phone = socket.socket()
# 实例化一个socket对象
phone.bind(("localhost",8088))
# 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址
phone.listen(5)
# 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
while 1: # 开启循环,多个用户同时连接(当然不是并发,排队连接)
conn,addr = phone.accept()
# 被动接受TCP客户端连接,(阻塞式)等待连接的到来,会有两个值,conn我也不明白是什么值,addr是客户端连接的地址
while 1: # 客户端与服务端多次对话,客户端多次执行循环
try: # 异常处理,客户端直接退出ConnectionResetError错误
from_client_data = conn.recv(1024) # 接收客户端数据
if from_client_data.upper() == b'Q':
# 判断客户端输入是否是q或Q,如果是q,直接退出当前连接
print("客户端退出")
break
print(from_client_data.decode('utf-8')) # 输出客户端转码后的数据
cmd_res = os.popen(from_client_data.decode("utf-8")).read() # 执行os命令,通过popen执行cmd命令
if len(cmd_res) == 0: # 如果没有该命令,返回下面结果
cmd_res = "cmd hs no output..."
conn.send(str(len(cmd_res.encode('gbk'))).encode('gbk')) # 发送数据,首先计算cmd_res的gbk字节长度,然后转换成字符串发送给客户端,因为int型不能发送
print(len(cmd_res.encode('gbk'))) # 输出该命令返回的长度
conn.send(cmd_res.encode('gbk')) # 执行一个接收,截断上下两个的粘包
conn.send(cmd_res.encode('gbk')) # 发送给客户端
except ConnectionResetError:
break
conn.close() # 关闭连接
phone.close() # 关闭连接
client端
import socket
phone = socket.socket() # 实例化对象
phone.connect(('localhost',8088)) # 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
while 1: # 循环输入
client_data = input(">>>")
if not client_data: # 如果输入为空,not client_data 则为True
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8")) # 给服务端发送信息
if client_data.upper() == "Q": # q退出
quit()
else:
server_data = phone.recv(1024) # 接收返回的字节长度
phone.send("准备好接收了".encode('utf-8')) # 给服务端发送消息,阻塞服务端上下造成粘包的问题(low版)
total_size = int(server_data.decode('gbk')) # 接收到的是字符串,转换成整型
total_data = b'' # 刚开始设置为0,空字符串则为0,前面加b表示字节
while 1: # 如果我收到的字节小于total_size,则一直循环
if len(total_data) < total_size:
total_data += phone.recv(1024) # 每次把信息加到total_data中
print(len(total_data))
else:
break
print(total_data.decode('gbk')) # 输出返回的结果
phone.close() # 关闭连接
struct模块解决粘包
server端
import socket
import subprocess
import struct
phone = socket.socket() # 实例化一个socket对象
phone.bind(("localhost",8088))
# 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址
phone.listen(5)
# 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
while 1:# 开启循环,多个用户同时连接(当然不是并发,排队连接)
conn,addr = phone.accept()
# 被动接受TCP客户端连接,(阻塞式)等待连接的到来,会有两个值,conn我也不明白是什么值,addr是客户端连接的地址
print(addr)
while 1: # 客户端与服务端多次对话,客户端多次执行循环
try: # 异常处理,客户端直接退出ConnectionResetError错误
from_client_data = conn.recv(1024) # 接收客户端数据
if from_client_data.upper() == b'Q': # 判断客户端输入是否是q或Q,如果是q,直接退出当前连接
print("客户端退出")
break
print(from_client_data.decode('utf-8')) # 输出客户端转码后的数据
obj = subprocess.Popen(from_client_data.decode('utf-8'),
shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)
# subprocess 模块中的代码
# shell: 命令解释器,相当于调用cmd 执行指定的命令。
# stdout:正确结果丢到管道中。
# stderr:错了丢到另一个管道中。
# windows操作系统的默认编码是gbk编码。
ret = obj.stdout.read()+obj.stderr.read() # 加的是字节
# 正确的输出跟错误的输出加起来,因为正确输出时,错误输出为空,所以加起来相当于0+1,没什么区别
total_size = len(ret) # 计算返回命令的长度
header = struct.pack('i',total_size) # 将一个数字转化成等长度的bytes类型。
print(total_size) # 打印出返回命令的长度
conn.send(header) # 发送固定长度的报头
conn.send(ret) # 给客户端发送返回命令的结果
except ConnectionResetError:
break
conn.close() # 关闭连接
phone.close() # 关闭连接
client端
import socket
import struct
phone = socket.socket() # 实例化对象
phone.connect(('localhost',8088)) # 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
while 1: # 循环输入
client_data = input(">>>")
if not client_data: # 如果输入为空,not client_data 则为True
print("发送的内容不能为空")
continue
phone.send(client_data.encode("utf-8")) # 给服务端发送信息
if client_data.upper() == "Q": # q退出
quit()
else:
server_data = phone.recv(4) # 接收报头长度
total_size = struct.unpack('i',server_data)[0] # 反解报头
total_data = b'' # 刚开始设置为0,空字符串则为0,前面加b表示字节
while 1: # 如果我收到的字节小于total_size,则一直循环
if len(total_data) < total_size:
total_data += phone.recv(1024) # 每次把信息加到total_data中
print(len(total_data))
else:
break
print(total_data.decode('gbk')) # 输出返回的结果,windows默认gbk
# print(int(server_data.decode('gbk')))
phone.close() # 关闭连接
解决socket粘包的两种low版模式 os.popen()和struct模块的更多相关文章
- 解决Socket粘包问题——C#代码
解决Socket粘包问题——C#代码 前天晚上,曾经的一个同事问我socket发送消息如果太频繁接收方就会有消息重叠,因为当时在外面,没有多加思考 第一反应还以为是多线程导致的数据不同步导致的,让他加 ...
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- Socket粘包问题终极解决方案—Netty版(2W字)!
上一篇我们讲了<Socket粘包问题的3种解决方案>,但没想到评论区竟然炸了.介于大家的热情讨论,以及不同的反馈意见,本文就来做一个扩展和延伸,试图找到问题的最优解,以及消息通讯的最优解决 ...
- 网络编程基础【day09】:解决socket粘包之大数据(七)
本节内容 概述 linux下运行效果 sleep解决粘包 服务端插入交互解决粘包问题 一.概述 刚刚我们在window的操作系统上,很完美的解决了,大数据量的数据传输出现的问题,但是在Linux环境下 ...
- 解决tcp粘包问题
目录 什么是粘包(演示粘包现象) 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地 ...
- python套接字解决tcp粘包问题
python套接字解决tcp粘包问题 目录 什么是粘包 演示粘包现象 解决粘包 实际应用 什么是粘包 首先只有tcp有粘包现象,udp没有粘包 socket收发消息的原理 发送端可以是一K一K地发送数 ...
- python网络编程基础之socket粘包现象
粘包现象两种 登陆 #服务端import json import socket server=socket.socket()#创建socket对象 ip_port=('127.0.0.1',8001) ...
- socket粘包现象加解决办法
socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...
- Socket粘包问题的3种解决方案,最后一种最完美!
在 Java 语言中,传统的 Socket 编程分为两种实现方式,这两种实现方式也对应着两种不同的传输层协议:TCP 协议和 UDP 协议,但作为互联网中最常用的传输层协议 TCP,在使用时却会导致粘 ...
随机推荐
- C++ 编程技巧锦集(一)
C++刷题精髓在STL编程,还有一些函数.下面我就总结一下本人在刷题过程中,每逢遇见总要百度的内容………………(大概率因为本人刷题太少了) 1. map map<string, int> ...
- QRowTable表格控件(二)-红涨绿跌
目录 一.开心一刻 二.概述 三.效果展示 四.任务需求 五.指定列排序 六.排序 七.列对其方式 八.相关文章 原文链接:QRowTable表格控件(二)-红涨绿跌 一.开心一刻 一天,五娃和六娃去 ...
- CSharp初级篇 1-4 this、索引器、静态、常量以及只读
.NET Core CSharp初级篇 1-4 本节内容为this.索引器.静态.常量以及只读 简介 在之前的课程中,我们谈论过了静态函数和字段的一小部分知识,本节内容中,我们将详细的讲解关于对象操作 ...
- Spring Bean 的装配方式
Spring Bean 的装配方式 装配 Bean 的三种方式 一个程序中,许多功能模块都是由多个为了实现相同业务而相互协作的组件构成的.而代码之间的相互联系又势必会带来耦合.耦合是个具有两面性的概念 ...
- 洛谷 P1970 花匠
题目描述 花匠栋栋种了一排花,每株花都有自己的高度.花儿越长越大,也越来越挤.栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致. 具体而 ...
- 简单题[期望DP]
也许更好的阅读体验 \(\mathcal{Description}\) 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻牌 ...
- InstantiationException:mybatis.spring.transaction.SpringManagedTransactionFactory
问题表现 Error creating bean with name 'sqlSessionFactory' Invocation of init method failed; nested exce ...
- Cocos2d-x 3.x 学习笔记(6):Sprite SpriteFrameCache Texture2D TextureCache
1. 概述 TextureCache是对Texture2D纹理的缓存,SpriteFrameCache是对SpriteFrame的缓存,每个SpriteFrame是对Texture2D的封装,Spri ...
- 简易数据分析 07 | Web Scraper 抓取多条内容
这是简易数据分析系列的第 7 篇文章. 在第 4 篇文章里,我讲解了如何抓取单个网页里的单类信息: 在第 5 篇文章里,我讲解了如何抓取多个网页里的单类信息: 今天我们要讲的是,如何抓取多个网页里的多 ...
- CentOS7 修改PATH环境变量的方法
vim /etc/profile 添加: PATH=/root/.config/composer/vendor/bin:$PATH 保存,退出,运行: source /etc/profile 检查: ...