学习笔记(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()

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于for循环中的变量int i 如果跳出了这个for循环后,i的值是继续保留还是被释放掉了

#include<iostream> using namespace std;int main() {char a[10]; //定义一个一维数组用来存放字符串int i,j; //定义变量cout<<"请输入字符&#xff1a;“;for(i0;i<10;i) //接收用户的输入{ ci…

keil优化等级设置

优化级别说明&#xff08;仅供参考&#xff09;&#xff1a;则其中的 Code Optimization 栏就是用来设置C51的优化级别。共有9个优化级别&#xff08;书上这么写的&#xff09;&#xff0c;高优化级别中包含了前面所有的优化级别。现将各个级别说明如下&#xff1a;0级优化&…

SVN命令使用详解

1、检出svn co http://路径(目录或文件的全路径) [本地目录全路径] --username 用户名 --password 密码svn co svn://路径(目录或文件的全路径) [本地目录全路径] --username 用户名 --password 密码svn checkout http://路径(目录或文件的全路径) [本地目录全路径]…

服务器排障 之 nginx 499 错误的解决

问题描述&#xff1a; Nginx 服务器大量499报错 220.181.165.136 - - [18/May/2015:10:31:02 0800] "POST /v1/jobsHTTP/1.1" 499 0 "" "bdHttpRequest/1.0.0"115.239.212.7 - - [18/May/2015:10:31:03 0800] "GET /v1/job/643309e3-dc73-4…

二叉查找树的先序遍历,中序遍历,后序遍历

1、有一个二叉查找树&#xff0c;存储者字符A,B,C,D,E,F,G,H,下面哪个结果是后序树遍历结果 A. ADBCEGFH B. BCAGEHFD C. BCAEFDHG D. BDACEFHG 我的结题思路是将每个答案按照后序的遍历方法把二叉树存储数据的结构还原&#xff0c;看是否满足二叉树的性质。 二叉树的性…

学习笔记(13):Python网络编程并发编程-解决粘包问题-终极版本

立即学习:https://edu.csdn.net/course/play/24458/296244?utm_sourceblogtoedu 粘包现象解决&#xff08;终极版&#xff09; 1.简单版的问题所在 1&#xff09;报头信息不一定只是包含着命令执行结果的字节数长度&#xff0c;在文件传输的时候也可能包含文件名等&#xff0c…

C#多态

C#多态 多态性&#xff08;C# 编程指南&#xff09;转自MSDN通过继承&#xff0c;一个类可以用作多种类型&#xff1a;可以用作它自己的类型、任何基类型&#xff0c;或者在实现接口时用作任何接口类型。这称为多态性。C# 中的每种类型都是多态的。类型可用作它们自己的类型或用…

Ubuntu 14.04.02 安装openvswitch-2.3.1

Open vSwitch安装 安装好操作系统 # lsb_release -a LSB Version: core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:core-4.1-amd64:core-4.1-noarch:security…

struts-上传

一、创建项目项目名称&#xff1a;demoupload二、添加jar包commons-fileupload-1.2.2.jarcommons-io-2.0.1.jarcommons-lang3-3.1.jarfreemarker-2.3.19.jarjavassist-3.11.0.GA.jarognl-3.0.5.jarstruts2-core-2.3.4.1.jarxwork-core-2.3.4.1.jar三、在web.xml文件中配置过滤器…

将数组作为参数,调用该函数时候给的是数组地址还是整个数组

1、在实际的应用中&#xff0c;数组经常作为函数参数&#xff0c;将数组中的数据传递到另外一个函数中&#xff0c;一般来说&#xff0c;传递可以采用两种方法&#xff1a; 1>、数组元素作为函数的实参时&#xff0c;用法跟普通变量作参数相同&#xff0c;将数组元素的值传递…

C#项目中常用到的设计模式

C#项目中常用到的设计模式 1. 引言 一个项目的通常都是从Demo开始&#xff0c;不断为项目添加新的功能以及重构&#xff0c;也许刚开始的时候代码显得非常凌乱&#xff0c;毫无设计可言。但是随着项目的迭代&#xff0c;往往需要将很多相同功能的代码抽取出来&#xff0c;这也是…

学习笔记(14):Python网络编程并发编程-文件传输功能实现

立即学习:https://edu.csdn.net/course/play/24458/296245?utm_sourceblogtoedu 1.课程目的&#xff1a; 实现客户端输入下载文件的命令&#xff0c;然后将命令发送给服务端&#xff0c;服务端再执行下载文件的命令&#xff0c;最后将执行下载文件命令后的结果返回给客户端&a…

NFS精简版配置方法

此实验的前提是防火墙需关闭。 1.关闭iptables /etc/init.d/iptables stop /etc/init.d/iptables status 2.关闭selinux setenforce 0 getenforce Permissive ---出现这个单词即代表selinux临时关闭&#xff0c;如需永久关闭则需修改/etc/sysconfig/selinux配置文件 …

Serializable接口中serialVersionUID字段的作用

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联&#xff0c;该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。 如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同&…

重新认知指针

1、把指针指向的变量的数据类型称为指针的数据类型&#xff1b;而任何一个指针变量本身数据值的类型都是unsigned long int 2.、指针变量名前的符号“*”表示的是指向运算。 3、不要认为“ *p" 是指针变量&#xff0c;指针变量是p而不是*p 4、

分布式数据库 HBase

原文地址&#xff1a;http://www.oschina.net/p/hbase/ HBase 概念 HBase – Hadoop Database&#xff0c;是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实…

学习笔记(15):Python网络编程并发编程-进程理论

立即学习:https://edu.csdn.net/course/play/24458/296423?utm_sourceblogtoedu 1.进程&#xff1a;正在运行的一个过程或者一个任务&#xff1b; 2.进程与程序的区别&#xff1a;程序是一堆代码&#xff0c;程序运行起来就是进程了&#xff0c;一个程序运行两次&#xff0c;算…

【翻译】Designing Websites for iPhone X

让网站适配 iphone X 英文原文地址&#xff1a;https://webkit.org/blog/7929/...本文原文地址&#xff1a;https://github.com/cnsnake11/... The section below about safe area insets was updated on Oct 31, 2017 to reflect changes in the iOS 11.2 beta. 以下关于safe …

指针作为函数参数引用数组的任意元素

void swap(int *a,int*b) {*a*a^*b;*b*a^*b;*a*a^*b; } swap(data[j],data[j1]&#xff09;; int data[10]{13,55,48,13,62,45,754,0,10};以上是我遇到的问题&#xff0c;我觉得调用这个swap函数是不能这样直接把数组的某个元素直接丢给swap数据 在程序中参加数据处理的量不是指…

使用 Log4Net 记录日志

第一步&#xff1a;下载Log4Net 下载地址&#xff1a;http://logging.apache.org/log4net/download_log4net.cgi 把下载的 log4net-1.2.11-bin-newkey解压后&#xff0c;如下图所示&#xff1a; 双击bin文件夹 双击net文件夹&#xff0c;选择针对.NET FramerWork的不同版本 找…