一. 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) # 100

 

# 客户端

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,粘包现象与解决办法,缓冲区的更多相关文章

  1. python之路--subprocess,粘包现象与解决办法,缓冲区

    一. subprocess 的简单用法 import subprocess sub_obj = subprocess.Popen( 'dir', #系统指令 shell=True, #固定方法 std ...

  2. socket粘包现象加解决办法

    socket粘包现象分析与解决方案 简单远程执行命令程序开发(内容回顾) res = subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=su ...

  3. Python socket粘包问题(初级解决办法)

    server端配置: import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) s ...

  4. TCP协议的粘包现象和解决方法

    # 粘包现象 # serverimport socket sk = socket.socket()sk.bind(('127.0.0.1', 8005))sk.listen() conn, addr ...

  5. socket基于TCP(粘包现象和处理)

    目录 6socket套接字 7基于TCP协议的socket简单的网络通信 AF_UNIX AF_INET(应用最广泛的一个) 报错类型 单一 链接+循环通信 远程命令 9.tcp 实例:远程执行命令 ...

  6. 什么是TCP粘包?怎么解决这个问题

    在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...

  7. python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议

    socket 基于tcp协议socket 服务端 import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买 ...

  8. python粘包分析与解决

    TCP与UDP协议 TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务器端)都要有一一成对的socket,因此 ...

  9. Python网络编程04 /recv工作原理、展示收发问题、粘包现象

    Python网络编程04 /recv工作原理.展示收发问题.粘包现象 目录 Python网络编程04 /recv工作原理.展示收发问题.粘包现象 1. recv工作原理 2. 展示收发问题示例 发多次 ...

随机推荐

  1. [Python]'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape 错误

    f = open('C:\Users\xu\Desktop\ceshi.txt') 这时报标题的错误信息 f = open(r'C:\Users\xu\Desktop\ceshi.txt') 改成这个 ...

  2. python 基础(八) os模块

    OS模块 概念:包含了普遍的操作 系统的功能 一.函数 函数名 函数说明 os.name 获取操作系统类型 nt->Windows posix->Linux/Unix os.listdir ...

  3. 个人常用Git操作记录

    本地分支与远程分支建立联系 Git - 新建本地分支与远程分支关联问题 查看本地分支与远程分支关系: git branch -vv 当前分支与远程分支建立关系: git branch --set-up ...

  4. 利用Common-BeanUtils封装请求参数

    一.BeanUtils介绍 commons-beanutils是利用反射机制对JavaBean的属性进行处理,提供了对于JavaBean的各种处理方法.众所周知,一个JavaBean通常包含了大量的属 ...

  5. c/c++学习系列之取整函数,数据宽度与对齐

    浮点数的取整 C/C++取整函数ceil(),floor() double floor(double x); double ceil(double x); 使用floor函数.floor(x)返回的是 ...

  6. 117 Populating Next Right Pointers in Each Node II 每个节点的右向指针 II

    这是“每个节点的右向指针”问题的进阶.如果给定的树可以是任何二叉树,该怎么办?你以前的解决方案仍然有效吗?注意:    你只能使用恒定的空间.例如,给定以下二叉树,         1       / ...

  7. 一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)

    一.负载均衡的简介: 负载均衡是高可用架构的一个关键组件,主要用来提高性能和可用性,通过负载均衡将流量分发到多个服务器,多服务器能够消除单个服务器的故障,减轻单个服务器的访问压力. 1.服务端负载均衡 ...

  8. vue2.0:(四)、首页入门,组件拆分1

    为什么需要组件拆分呢?这样才能更符合模块化这样一个理念. 首先是index.html,代码如下: <!DOCTYPE html> <html> <head> < ...

  9. ios,弹窗遮罩滚动穿透解决方案

  10. 提升 Web开发性能的 10 个技巧

    随着网络的高速发展,网络性能的持续提高成为能否在芸芸App中脱颖而出的关键.高度联结的世界意味着用户对网络体验提出了更严苛的要求.假如你的网站不能做到快速响应,又或你的App存在延迟,用户很快就会移情 ...