python之路--subprocess,粘包现象与解决办法,缓冲区
一. subprocess 的简单用法
import subprocess
sub_obj = subprocess.Popen(
'dir', #系统指令
shell=True, #固定方法
stdout=subprocess.PIPE, #标准输出 PIPE 管道,保存着指令的执行结果
stderr=subprocess.PIPE #标准错误输出
)
# dir 当前操作系统(Windows)的命令,会执行stdout
print('正确输出',sub_obj.stdout.read().decode('gbk'))
# 如果是 'ls' 是Linux里的命令 会执行stderr ,因为系统的编码是gbk
print('错误输出',sub_obj.stderr.read().decode('gbk'))
二 .两种粘包现象
1 连续的小包可能会被优化算法给组合到一起进行发送
# 客户端 import socket
BUFSIZE=1024
ip_port=('127.0.0.1',8080)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# res=s.connect_ex(ip_port)
res=s.connect(ip_port)
# 这边分两段发送
s.send('hi'.encode('utf-8'))
s.send('meinv'.encode('utf-8')) # 服务端 from socket import *
ip_port=('127.0.0.1',8080)
tcp_socket_server=socket(AF_INET,SOCK_STREAM)
tcp_socket_server.bind(ip_port)
tcp_socket_server.listen(5)
conn,addr=tcp_socket_server.accept()
#服务端连接接收两个信息
data1 = conn.recv(10)
data2 = conn.recv(10)
# 如果网络良好的话 收到的应该是 一条信息himeinv
print('----->',data1.decode('utf-8'))
print('----->',data2.decode('utf-8'))
conn.close()
2 第一次如果发送的数据大小2000B接收端一次性接受大小为1024,这就导致剩下的内容会被下一次recv接收到,导致结果错乱
# 客户端 import socket client = socket.socket()
client.connect(('127.0.0.1',8001))
while 1:
cmd = input('请输入指令:') client.send(cmd.encode('utf-8'))
# 这里写1025是因为粘包的原因需要写1025才能正好接收到完整的字
server_cmd_result = client.recv(1025) print(server_cmd_result.decode('gbk')) # 服务端 import socket
import subprocess
server = socket.socket()
ip_port = ('127.0.0.1',8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_cmd = conn.recv(1024)
print(from_client_cmd.decode('utf-8'))
sub_obj = subprocess.Popen(
from_client_cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
std_msg = sub_obj.stdout.read()
print('指令的执行结果长度>>>>',len(std_msg))
conn.send(std_msg)
三 . 解决粘包现象的方法
方案一:由于双方不知道对方发送数据的长度,导致接收的时候,可能接收不全,或者多接收另外一次发送的信息内容,所以在发送真实数据之前,
要先发送数据的长度,接收端根据长度来接收后面的真实数据,但是双方有一个交互确认的过程.
# 客户端 import socket
client = socket.socket()
client.connect(('127.0.0.1',8001))
while 1:
cmd = input('请输入指令:')
client.send(cmd.encode('utf-8'))
server_res_len = client.recv(1024).decode('utf-8')
print('来自服务端的消息长度',server_res_len)
# 告知服务端已经接收到了长度
client.send(b'ok')
# 接收所有发过来的所有字节的长度
server_cmd_result = client.recv(int(server_res_len))
print(server_cmd_result.decode('gbk')) # 服务端 import socket
import subprocess
server = socket.socket()
ip_port = ('127.0.0.1',8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_cmd = conn.recv(1024)
print(from_client_cmd.decode('utf-8'))
#接收到客户端发送来的系统指令,我服务端通过subprocess模块到服务端自己的系统里面执行这条指令
sub_obj = subprocess.Popen(
from_client_cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE, #正确结果的存放位置
stderr=subprocess.PIPE #错误结果的存放位置
)
#从管道里面拿出结果,通过subprocess.Popen的实例化对象.stdout.read()方法来获取管道中的结果
std_msg = sub_obj.stdout.read()
#为了解决黏包现象,我们统计了一下消息的长度,先将消息的长度发送给客户端,客户端通过这个长度来接收后面我们要发送的真实数据
std_msg_len = len(std_msg)
#首先将数据长度的数据类型转换为bytes类型
std_bytes_len = str(len(std_msg)).encode('utf-8')
print('指令的执行结果长度>>>>',len(std_msg))
conn.send(std_bytes_len)
# 确认一下客户端是否收到
status = conn.recv(1024)
if status.decode('utf-8') == 'ok':
conn.send(std_msg)
else:
pass
方案二:
struct模块,
打包:struct.pack(‘i’,长度)
解包:struct.unpack(‘i’,字节)
# struct 的简单用法
import struct
num = 100
#打包,将int类型的数据打包成4个长度的bytes类型的数据
byt = struct.pack('i',num)
print(byt) # b'd\x00\x00\x00'
#解包,将bytes类型的数据,转换为对应的那个int类型的数据
# int_num = struct.unpack('i',byt)
# print(int_num) # (100,)
int_num = struct.unpack('i',byt)[0]
print(int_num) #
# 客户端 import socket
import struct
client = socket.socket()
client.connect(('127.0.0.1',8001)) while 1:
cmd = input('请输入指令:')
#发送指令
client.send(cmd.encode('utf-8'))
#接收数据长度,首先接收4个字节长度的数据,因为这个4个字节是长度
server_res_len = client.recv(4)
msg_len = struct.unpack('i',server_res_len)[0]
print('来自服务端的消息长度',msg_len)
#通过解包出来的长度,来接收后面的真实数据
server_cmd_result = client.recv(msg_len)
print(server_cmd_result.decode('gbk')) # 服务端 import socket
import subprocess
import struct
server = socket.socket()
ip_port = ('127.0.0.1',8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_cmd = conn.recv(1024)
print(from_client_cmd.decode('utf-8'))
#接收到客户端发送来的系统指令,我服务端通过subprocess模块到服务端自己的系统里面执行这条指令
sub_obj = subprocess.Popen(
from_client_cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE, #正确结果的存放位置
stderr=subprocess.PIPE #错误结果的存放位置
)
#从管道里面拿出结果,通过subprocess.Popen的实例化对象.stdout.read()方法来获取管道中的结果
std_msg = sub_obj.stdout.read()
#为了解决黏包现象,我们统计了一下消息的长度,先将消息的长度发送给客户端,客户端通过这个长度来接收后面我们要发送的真实数据
std_msg_len = len(std_msg)
print('指令的执行结果长度>>>>',len(std_msg))
msg_lenint_struct = struct.pack('i',std_msg_len)
conn.send(msg_lenint_struct+std_msg)
四 . 缓冲区

python之路--subprocess,粘包现象与解决办法,缓冲区的更多相关文章
- python--subprocess,粘包现象与解决办法,缓冲区
一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...
- socket粘包现象加解决办法
socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...
- TCP协议的粘包现象和解决方法
# 粘包现象 # serverimport socket sk = socket.socket()sk.bind(('127.0.0.1', 8005))sk.listen() conn, addr ...
- 百万年薪python之路 -- socket粘包问题解决
socket粘包问题解决 1. 高大上版解决粘包方式(自定制包头) 整体的流程解释 整个流程的大致解释: 我们可以把报头做成字典,字典里包含将要发送的真实数据的描述信息(大小啊之类的),然后json序 ...
- Python socket粘包问题(初级解决办法)
server端配置: import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) s ...
- socket基于TCP(粘包现象和处理)
目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...
- 什么是TCP粘包?怎么解决这个问题
在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...
- Python之路(第三十一篇) 网络编程:简单的tcp套接字通信、粘包现象
一.简单的tcp套接字通信 套接字通信的一般流程 服务端 server = socket() #创建服务器套接字 server.bind() #把地址绑定到套接字,网络地址加端口 server.lis ...
- python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议
socket 基于tcp协议socket 服务端 import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买 ...
随机推荐
- JWT(JSON Web Token)
摘要: 在Web应用中,使用JWT替代session并不是个好主意 适合JWT的使用场景 抱歉,当了回标题党.我并不否认JWT的价值,只是它经常被误用. 什么是JWT 根据维基百科的定义,JSON W ...
- 转://Oracle 数据备份与恢复微实践
1.模拟控制文件丢失后的数据库恢复(完全恢复) 今天的主题是备份与恢复,目的就是保护数据的安全性,众所周知Oracle之所以在市场上占据了50%的份额,与它提供了强大的数据保护措施是分不开的,下面我们 ...
- GIF 生成软件
Screen to Gif
- mac sourcetree push分支选中所有tag的时候报错
错误信息: ....... ! [rejected] 573_0811_stable -> 573_0811_stable (already exists)updating local trac ...
- JVM调优常用参数和注意点备忘录
本文主要是工作过程中总结的一些jvm调优的参数和注意的地方,作为一个备忘录,先占个坑,有时间在来细化具体的实例. gc日志是覆盖的方式如果文件名字固定会导致上一次被覆盖可以采用这个-Xloggc:ba ...
- React 系列教程
英文版:https://reactjs.org/docs/create-a-new-react-app.html 中文版:https://doc.react-china.org/docs/hello- ...
- 【原创】分布式之elk日志架构的演进
引言 好久没写分布式系列的文章了,最近刚好有个朋友给我留言,想看这方面的知识.其实这方面的知识,网上各种技术峰会的资料一抓一大把.博主也是凑合着写写.感觉自己也写不出什么新意,大家也凑合看看. 日志系 ...
- ML.NET 示例:聚类之鸢尾花
写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...
- 如何查看IntelliJ IDEA的版本信息
作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. IDEA的版本信息问题 额,说实在的,这篇文章十三一开始也不是很想整 ...
- 一款优秀的前端框架——AngularJS
前 言 AngularJS是一款为了克服HTML在构建应用上的不足而设计的优秀的前端JS框架.AngularJS有着诸多特性,最为核心的是:MVC.模块化.自动化双向数据绑定.语义化标签.依赖注 ...