解决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# Linq 常用查询操作符
限定操作: 1. All:用来确定是否序列中的所有元素都满足条件 2. Any:用来确定序列是否包含任何元素,有参方式用来确定序列中是否有元素满足条件 3. Contains:方法用来确定序列是否包含 ...
- springboot项目快速搭建
1. 问题描述 springboot的面世,成为Java开发者的一大福音,大大提升了开发的效率,其实springboot只是在maven的基础上,对已有的maven gav进行了封装而已,今天用最简单 ...
- 多线程总结-同步之ReentrantLock
目录 1 ReentrantLock与synchronized对比 2.示例用法 2.1 基本用法 2.2 尝试锁 2.3 可打断 2.4 公平锁 1 ReentrantLock与synchroniz ...
- 1.svn 彻底clear时,注意代码备份 2.借助vc助手加头文件
1.svn 彻底clear时,注意代码备份 2.不小心彻底clear可以在回收站找到 3.借助vc助手加头文件
- Sequencial Minimal Optimization-a Fast Alg for Training SVM(译文)
- C语言入门5-键盘的输入和屏幕输出
C程序中的键盘输入和屏幕输出都是通过 调用输入/输出函数 实现的. 一.数据的格式化 屏幕输出 函数printf()的一般格式 (有两种) (1)第一种: printf(格式控制字符串): ...
- springboot的邮件服务
作者:纯洁的微笑出处:http://www.ityouknow.com/ 版权归作者所有,转载请注明出处 springboot仍然在狂速发展,才五个多月没有关注,现在看官网已经到1.5.3.RELEA ...
- TestNG中DataProvider的用法二:简单的数据驱动
@DataProvider标记的方法除了可以返回数组外,还可以返回一个Iterator,这样的好处是不用把所有的测试数据都加载到内存中,而是需要的时候就读一条. 下面的例子就使用了Iterator,然 ...
- 14. 流、文件和IO
前言 InputStream/OutStream流用来处理设备之间的数据传输 Java.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持 ...
- 语音控制单片机工作【百度语音识别,串口发送数据到单片机】【pyqt源码+软件】!!
前些天闲着没事,就做了个语音识别结合串口发送指令的软件,用的是pyqt写的,软件打开后对着笔记本的话筒说话, 他就能识别返回文字结果,然后匹配语音中的关键词,如果有关键词就发送关键词对应的命令,比如语 ...