学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本
立即学习:https://edu.csdn.net/course/play/24458/296243?utm_source=blogtoedu
粘包现象的解决:简单版
1.思路:
在服务器端计算出执行命令后结果的字节长度,然后再将字节数长度send即通知给客户端,客户端根据这个字节数的长度一次性即可将相应的命令执行结果给接收,进而解决了粘包问题。
2.知识点:
1)互联网协议:报头+数据
2)报头是固定长度字节的,一般是4字节数,包含了一段数据的相关信息,如数据的字节总数以及相关描述等;
3)struct模块,是python内置模块,用于报头的相关函数,如res = struct.pack('i',信息)是用于定制固定长度的函数,得到的是一个对象,而struct.unpack('i',res)则是解析报头的函数,得到的是一个元组,第一个元素为字节数长度
3.关键代码
'''
服务端
'''......#1接收客户端发送过来的命令cmd = conn.recv(1024)#2处理命令,执行命令并且获得命令得到的结果obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,#将正确运行命令得到的结果传给管道stdout中stderr=subprocess.PIPE)#将没有正确运行命令得到的返回信息存放在stderr管道中stdout = obj.stdout.read()stderr = obj.stderr.read()total_size = len(stderr + stdout)#1)定制固定长度的报头,报头包含命令执行结果的字节数长度header = struct.pack('i',total_size)#2)将报头发送给客户端conn.send(header)#3)将真实的命令执行结果信息发送给客户端data = stdout + stderrconn.send(data)......'''
客户端
'''.......#4、接收服务器返回来的数据recv()#1)先接收由服务器返回来的报头,报头是固定长度的,因此取前面4字节的数据即为报头header = phone.recv(4)#返回的是一个对象#2)解析返回的报头,获得字节数总长信息obj_truple = struct.unpack('i',header)#返回的是一个元组total_size = obj_truple[0]#取元组第一个元素即为总字节数#3)接收真实的命令执行结果信息recv_size = 0data = b''while recv_size < total_size:recv_data = phone.recv(1024)#接收小于1024bytes的数据recv_size += len(recv_data)data += recv_dataprint('服务器返回来的数据:',data.decode('gbk')).......
结果:由结果可以得到,输入相应的命令可以得到正确的命令执行结果
#第一个命令
请输入:dir
服务器返回来的数据: 驱动器 C 中的卷是 本地磁盘
卷的序列号是 B476-3C7C
C:\Users\jinlin\Desktop\python_further_study\socket编程\粘包现象解决(简单版) 的目录
2020/03/09 14:46 <DIR> .
2020/03/09 14:46 <DIR> ..
2020/03/09 14:46 1,503 客户端(粘包).py
2020/03/09 14:45 1,434 服务器端(粘包).py
2 个文件 2,937 字节
2 个目录 122,025,189,376 可用字节
#第二个命令
请输入:tasklist
服务器返回来的数据:
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 4 K
System 4 Services 0 568 K
smss.exe 324 Services 0 784 K
csrss.exe 524 Services 0 8,760 K
csrss.exe 620 Console 1 37,232 K
wininit.exe 628 Services 0 3,940 K
winlogon.exe 656 Console 1 6,564 K
..............
cmd.exe 11188 Console 1 2,304 K
tasklist.exe 9056 Console 1 6,176 K
#第三个命令
请输入:dir
服务器返回来的数据: 驱动器 C 中的卷是 本地磁盘
卷的序列号是 B476-3C7C
C:\Users\jinlin\Desktop\python_further_study\socket编程\粘包现象解决(简单版) 的目录
2020/03/09 14:46 <DIR> .
2020/03/09 14:46 <DIR> ..
2020/03/09 14:46 1,503 客户端(粘包).py
2020/03/09 14:45 1,434 服务器端(粘包).py
2 个文件 2,937 字节
2 个目录 122,024,615,936 可用字节
4.完整代码
'''
服务端
'''
import socket
import subprocess
import struct
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
while True:#接收客户端发送过来连接服务器请求res = phone.accept()conn,client_addr = reswhile True:try:#1接收客户端发送过来的命令cmd = conn.recv(1024)#2处理命令,执行命令并且获得命令得到的结果obj = subprocess.Popen(cmd.decode('utf-8'),shell=True,stdout=subprocess.PIPE,#将正确运行命令得到的结果传给管道stdout中stderr=subprocess.PIPE)#将没有正确运行命令得到的返回信息存放在stderr管道中stdout = obj.stdout.read()stderr = obj.stderr.read()total_size = len(stderr + stdout)#1)定制固定长度的报头,报头包含命令执行结果的字节数长度header = struct.pack('i',total_size)#2)将报头发送给客户端conn.send(header)#3)将真实的命令执行结果信息发送给客户端data = stdout + stderrconn.send(data)except ConnectionResetError:breakconn.close()
phone.close()
phone.close()
'''
客户端
'''
#导入模块
import socket
import struct#1、设置phone套接字
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#2、连接服务器(打电话),本地地址:127.0.0.1
phone.connect(('127.0.0.1',8080))#3、向服务器发送请求send(),发送的数据不能直接发送字符串,因为要传送到物理层底层,因此需要转换成二进制的bytes类型进行发送,只需:发送的数据.encode('utf-8')即可
while True:cmd = input("请输入:")#修复客户端发送空字符串而服务器卡在接收信息处的bug,continue表示跳出本次循环,重新开始下一次的循环if not cmd:continuephone.send(cmd.encode('utf-8'))#4、接收服务器返回来的数据recv()#1)先接收由服务器返回来的报头,报头是固定长度的,因此取前面4字节的数据即为报头header = phone.recv(4)#返回的是一个对象#2)解析返回的报头,获得字节数总长信息obj_truple = struct.unpack('i',header)#返回的是一个元组total_size = obj_truple[0]#取元组第一个元素即为总字节数#3)接收真实的命令执行结果信息recv_size = 0data = b''while recv_size < total_size:recv_data = phone.recv(1024)#接收小于1024bytes的数据recv_size += len(recv_data)data += recv_dataprint('服务器返回来的数据:',data.decode('gbk'))#5、关闭套接字phone
phone.close()
学习笔记(12):Python网络编程并发编程-解决粘包问题-简单版本相关推荐
- ros学习笔记12——python实现发布和接收ros topic
ros学习笔记12--python实现发布和接收ros topic 一.简单demo 1.工作空间是存放工程开发的相关文件的文件夹 2.创作工作空间指令 3 .创建功能包 4. 创建Topic的订阅发 ...
- 【Python】网络编程--解决粘包问题--简单版:
网络编程–解决粘包问题–简单版: 客户端: import struct import socketphone=socket.socket(socket.AF_INET,socket.SOCK_STRE ...
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...
- python3第三方库手册_python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑...
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...
- 学习笔记(11):Python网络编程并发编程-粘包底层原理分析
立即学习:https://edu.csdn.net/course/play/24458/296241?utm_source=blogtoedu 1.send和recv底层分析 1)不管是recv还是 ...
- Python网络与并发编程 02 TCP粘包
TCP/Socket与subprocess 我们准备做一个可以在Client端远程执行Server端的shell命令并拿到其执行结果的程序,而涉及到网络通信就必然会使用到socket模块,此外还需要s ...
- 学习笔记(19):Python网络编程并发编程-互斥锁
立即学习:https://edu.csdn.net/course/play/24458/296430?utm_source=blogtoedu 1.互斥锁: 多进程间的内存是相互隔离的,因此其数据也是 ...
- 学习笔记(34):Python网络编程并发编程-异步调用与回调机制
立即学习:https://edu.csdn.net/course/play/24458/296452?utm_source=blogtoedu 1.知识点:(详细见代码注释) 1)同步调用: res1 ...
- 学习笔记(33):Python网络编程并发编程-进程池线程池
立即学习:https://edu.csdn.net/course/play/24458/296451?utm_source=blogtoedu 进程池与线程池: 一般应用在网站上,进程池或线程池最大的 ...
最新文章
- ios自定义日期、时间、城市选择器
- javascript:使用document.getElementById读取数据为空分析
- No changes detected解决方案
- 安卓系统被限制之后,华为手机如何在海外市场销售?
- Linux内核的Makefile和kconfig解读
- 2017.10.14 【FOTILE模拟赛】L 失败总结
- [Ext JS 4]性能优化
- Leetcode 218.天际线问题
- loadRunner函数之lr_set_debug_message
- DNSBIND——DNS的ACL和视图
- python做图像处理程序_python图像处理之镜像实现方法
- 单片机控制步进电机程序c语言正反转停止,单片机控制步进电机正反转程序
- iphone投屏老是显示无法连接服务器,iphone怎么投屏到电视 升级iOS11后为什么投屏会失败...
- Java---设计【高校教师信息管理系统】
- 提供可用的BT5更新源,亲测可用
- 看完了团长,我没有心理在去看《南京!南京!》
- RECON-NG介绍及使用
- 安卓模拟器错误: Could not open
- Java. JFrame简单画图
- 还在想假期去哪玩?直接做一个旅游攻略小程序