解决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++学习书籍推荐《The C++ Programming Language第四版》下载
百度云及其他网盘下载地址:点我 作者简介 Bjarne Stroustrup is the designer and original implementer of C++, the author o ...
- SQL Server 根据日期分组、 根据时间段分组(每三个小时一组)
所用数据表: 一.根据日期分组 1. 使用convert() 函数方式 --根据年月 ),CreatTime,)日期,COUNT(*) 次数,sum(Money)总数 from Orders ),Cr ...
- C# ExcelAddIn 开发笔记
好久都没有写博客了,最近真的是太忙了,接手公司要做的一个小的新的项目,从接触认识到一个新东西,再到自己琢磨研究,最终结合公司业务把整个excel插件项目完成,还是有一点点成就感.以下是项目中基本上大致 ...
- 关于vue项目font字体图标库导入未显示的问题
运行项目时,弹出以下信息:
- github访问不到,登陆不上
为github添加host C:\WINDOWS\System32\drivers\etc 在host文件添加如下两行 192.30.253.112 github.com 151.101.113.19 ...
- Excel催化剂开源第34波-SM.MS图床API调用(用POST上传multipart/form-data内容)
日常做网抓数据,都是以GET请求为主,偶尔遇到需要POST请求的,一般POST的参数只是一串字符串就可以了,通过构造字符串也很容易完成,但此次SM.MS的API接口要求是Content-Type: m ...
- 面向对象和pickle模块结合
面向对象和pickle模块相关 1.面向对象: class 类名: def init(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法 ...
- C# MATLAB混编(一)
参照这篇博客进行的C# MATLAB混编学习,学习过程中文章中的一些问题我并没有遇到,但是我遇到了一些新问题,这些问题的解决办法将在下一篇博客给出. 配置环境:vs2010(64位)+Matlab20 ...
- python课堂整理15---map, filter,reduce函数
一.map函数 处理序列(可迭代对象)中的每一个元素,得到的结果是一个‘列表’(其实是个迭代器),该‘列表’元素个数及位置与原来一样 理解下面这段代码: num_l = [1, 2, 4, 6] de ...
- python初步编写用户登录
python初步编写用户登录 python编写用户登录 用python写一个脚本,使得这个脚本在执行后,可以产生如下的效果: 1.用户的账号为:root 密码为:westos 2.用户账号和密码均输 ...