网络通信与并发编程(三)粘包现象解决方案、socketserver实现并发

粘包现象解决方案、socketserver实现并发

文章目录

  • 粘包现象解决方案、socketserver实现并发
  • 一、粘包现象解决方案
    • 1.发送数据大小
    • 2.发送数据信息
  • 二、socketserver实现并发
    • 1.tcp版的socketserver并发
    • 2.udp版的socketserver并发

一、粘包现象解决方案

1.发送数据大小

有了上一篇文章的分析,我们知道tcp协议之所以会出现粘包现象,是因为无法得知每次传输的字节数。如果我们人为的给传输的数据添加一个报头用来表示接收内容的字节数就可以解决这个问题了。

#服务端
from socket import *
import subprocess
import structserver=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)while True:conn,client_addr=server.accept()while True:try:cmd=conn.recv(1024)if len(cmd) == 0:breakobj=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)stdout=obj.stdout.read()stderr=obj.stderr.read()#1、制作报头(固定长度)total_size=len(stdout) + len(stderr)#struct模块可以将一个数据类型转为固定长度的bytesheader=struct.pack('i',total_size)#2、发送固定长度的报头conn.send(header)#3、发送真实的数据conn.send(stdout)conn.send(stderr)except ConnectionResetError:breakconn.close()
#客户端
from socket import *
import structclient=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))while True:cmd=input('>>: ').strip()if len(cmd) == 0:continueclient.send(cmd.encode('utf-8'))#1、接收固定长度的报头(bytes)header=client.recv(4)#从报头中解析接收内容的字节数total_size=struct.unpack('i',header)[0]#2、接收真实的数据#recv_size表示已接收字节数,total_size表示总的字节数recv_size=0res=b''while recv_size < total_size :data=client.recv(1024)res+=datarecv_size+=len(data)print(res.decode('gbk'))

接收结果:
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 8 K
System 4 Services 0 152 K
(接收内容过长,中间部分略去)
tasklist.exe 16076 Console 1 9,520 K
WmiPrvSE.exe 15416 Services 0 10,212 K

2.发送数据信息

在一般的文件传输中,我们除了可以看到文件的大小,还可以看见文件名称,创建日期当信息,为了将这些信息加入到报头中,我们可以将上面的代码进一步优化为如下形式:

#服务端
from socket import *
import subprocess
import struct
import json,timeserver=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)while True:conn,client_addr=server.accept()while True:try:cmd=conn.recv(1024)if len(cmd) == 0:break# 运行系统命令obj=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)stdout=obj.stdout.read()stderr=obj.stderr.read()#将报头信息制作成字典header_dic={'filename':'tasklist','total_size':len(stdout) + len(stderr),'create_time':time.strftime('%Y-%m-%d %H')}#通过json格式将报头字典转为bytesheader_json=json.dumps(header_dic)header_bytes=header_json.encode('utf-8')#由于报头字典大小超出struct的限制,所以此处先发送4个字节标识报头字典的大小#1、发送报头字典大小conn.send(struct.pack('i',len(header_bytes)))#2、发送报头字典conn.send(header_bytes)#3、发送真实的数据conn.send(stdout)conn.send(stderr)except ConnectionResetError:breakconn.close()
#客户端
from socket import *
import struct
import jsonclient=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))while True:cmd=input('>>: ').strip()if len(cmd) == 0:continueclient.send(cmd.encode('utf-8'))#1、收4个字节,这4个字节表示报头长度header_len=struct.unpack('i',client.recv(4))[0]#2、再接收报头header_bytes=client.recv(header_len)#通过json解析出报头字典header_json=header_bytes.decode('utf-8')header_dic=json.loads(header_json)print(header_dic)total_size=header_dic['total_size']#3、接收真实的数据recv_size=0res=b''while recv_size < total_size :data=client.recv(1024)res+=datarecv_size+=len(data)print(res.decode('gbk'))

可以看到结果中接收到了报头信息:
{‘filename’: ‘tasklist’, ‘total_size’: 17942, ‘create_time’: ‘2024-10-18 18’}
映像名称 PID 会话名 会话# 内存使用
========================= ======== ================ =========== ============
System Idle Process 0 Services 0 8 K
System 4 Services 0 152 K
(接收内容过长,中间部分略去)
tasklist.exe 16076 Console 1 9,520 K
WmiPrvSE.exe 15416 Services 0 10,212 K

二、socketserver实现并发

1.tcp版的socketserver并发

#客户端
import socket
#表示当前开启的客户端序号
#并发通信时,可以开启斗个客户端与服务端通信
num=33
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080)) while True:msg = 'client%s'%numif len(msg) == 0:continuephone.send(msg.encode('utf-8'))data=phone.recv(1024)print(data)phone.close()
#服务端
import socketserver
#MyHandler为自定义的通信函数
class MyHandler(socketserver.BaseRequestHandler):#MyHandler继承了abc类,必须复写handle函数def handle(self):#通信循环while True:try:#self.request中存放这通信连接#self.client_address中存放着客户端的ip和端口号#self.server中存放着套接字对象data=self.request.recv(1024)if len(data) == 0:breakself.request.send(data.upper())except ConnectionResetError:breakif __name__ == '__main__':#创建socketserver对象s=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyHandler,bind_and_activate=True)#serve_forever函数在有客户端发送请求时创建一个线程#这个线程会根据建立的通信链接与客户端通信(创建MyHandler对象并调用handle方法)s.serve_forever()

2.udp版的socketserver并发

#客户端
import socket
num=33
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:msg='client%s'%numclient.sendto(msg.encode('utf-8'),('127.0.0.1',8080))data,server_addr=client.recvfrom(1024)print(data)client.close()
#服务端
import socketserver
class MyHandler(socketserver.BaseRequestHandler):def handle(self):# 通信循环#self.request[1]存放着套接字对象#self.client_address存放着客户端的信息#self.request[0]存放着客户端发送的信息data = self.request[0]self.request[1].sendto(data.upper(), self.client_address)if __name__ == '__main__':s = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyHandler)#当客户端发送信息以后,serve_forever函数会创建一个线程与客户端进行通信s.serve_forever()

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

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

相关文章

Redis 的安装与部署(图文)

前言 Redis 暂不支持Windows 系统&#xff0c;官网上只能下载Linux 环境的安装包。但是启用WSL2 就可以在Windows 上运行Linux 二进制文件。[要使此方法工作&#xff0c;需要运行Windows 10 2004版及更高版本或Windows 11]。本文在CentOS Linux 系统上安装最新版Redis&#xf…

力扣10.18

1463. 摘樱桃 II 给你一个 rows x cols 的矩阵 grid 来表示一块樱桃地。 grid 中每个格子的数字表示你能获得的樱桃数目。 你有两个机器人帮你收集樱桃&#xff0c;机器人 1 从左上角格子 (0,0) 出发&#xff0c;机器人 2 从右上角格子 (0, cols-1) 出发。 请你按照如下规则…

php常用设计模式之单例模式

设计模式是我们日常开发中最常用的编程模式之一&#xff0c;也是面试中最高频的考点之一。通过合理运用设计模式&#xff0c;可以使代码结构更加清晰、易于维护。通过这篇文章 我也讲一下设计模式中的单例模式&#xff0c;了解下它的原理和适用场景。 单例模式 单例模式&…

ArcGIS 最新底图服务地址

ArcGIS 最新底图服务地址 说明 先上地址&#xff1a; 地形图&#xff1a; https://services.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer深色地形图&#xff1a;https://services.arcgisonline.com/arcgis/rest/services/Elevation/World_Hi…

【C++】unordered_set、unordered_map超详细封装过程,处理底层细节

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言1、数据泛型2、迭代器2.1 重载2.2 begin、end2.3 const迭代器2.4 unordered_map中[]重载 3、特殊类型 总结 前…

如何设计开发RTSP直播播放器?

技术背景 我们在对接RTSP直播播放器相关技术诉求的时候&#xff0c;好多开发者&#xff0c;除了选用成熟的RTSP播放器外&#xff0c;还想知其然知其所以然&#xff0c;对RTSP播放器的整体开发有个基础的了解&#xff0c;方便方案之作和技术延伸。本文抛砖引玉&#xff0c;做个…

Unity 实战案例全解析 实现时间停止效果+世界变灰

画面里运动的那个小玩意这么写 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Partol : MonoBehaviour {public Transform pos1;public Transform pos2;public float speed;private Transform target;void Start() {target p…

前端开发攻略---取消已经发出但是还未响应的网络请求

目录 注意&#xff1a; 1、Axios实现 2、Fetch实现 3、XHR实现 注意&#xff1a; 当请求被取消时&#xff0c;只会本地停止处理此次请求&#xff0c;服务器仍然可能已经接收到了并处理了该请求。开发时应当及时和后端进行友好沟通。 1、Axios实现 <!DOCTYPE html> &…

性能测试工具JMeter

本次使用的博客系统的url&#xff1a; http://8.137.19.140:9090/blog_edit.html 1. JMeter介绍 环境要求&#xff1a;要求java&#xff0c;jdk版本大于8&#xff1b; Apache JMeter 是 Apache 组织基于 Java 开发的压⼒测试⼯具&#xff0c;⽤于对软件做性能测试&#xff1b…

【Next.js 项目实战系列】06-身份验证

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】05-删除 Issue 身份验证 配置 Next-Auth​ 本节代码链接 具体内容可参考Authenti…

带新手用一套坦克大战搞定Java核心编程

有不少在校大学生朋友私信笔者&#xff0c;觉得现在的Java教程学的比较枯燥&#xff0c;有没有能学到基础知识同时还有做项目感觉的教程。因为笔者最早接触Java时学的是马士兵老师、韩顺平老师这样的大佬当时出的教程&#xff0c;尤其印象深刻的是二位大佬的坦克大战项目&#…

基于DSP+ARM+FPGA的电能质量分析仪的软件设计

软件设计是电能质量设备的核心内容&#xff0c;上述章节详细介绍了电能质量参数的 算法&#xff0c;并且通过仿真实验进行了验证&#xff0c;本章将结合现代电能质量监测设备需求实 现算法在实际电网中应用。根据设计的电能质量分析仪的需求分析&#xff0c;进行总体的 软件…

Java筑基之路:运算符深入(下)

&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d; &#x1f947;博主昵称&#xff1a;小菜元 &#x1f35f;博客主页…

华为开发者论坛入口

这个才是华为开发者论坛网址&#xff0c;被百度搜出的鸿蒙论坛搞死。 华为云论坛_云计算论坛_开发者论坛_技术论坛-华为云 (huaweicloud.com) 备份&#xff1a; https://bbs.huaweicloud.com/

芯科科技最新第三代无线开发平台全面提升人工智能和无线连接功能!

芯科科技展示人工智能在塑造无线连接技术未来发挥的作用 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;&#xff0c;日前在首届北美嵌入式世界展览会&…

计算机网络:数据链路层 —— 共享式以太网

文章目录 共享式以太网CSMA/CD 协议CSMA/CD 协议 的基本原理 共享式以太网的争用期共享式以太网的最小帧长共享式以太网的最大帧长共享式以太网的退避算法截断二进制指数退避算法 共享二进制以太网的信道利用率使用集线器的共享式以太网10BASE-T 共享式以太网 共享式以太网是当…

51单片机数码管循环显示0~f

原理图&#xff1a; #include <reg52.h>sbit dulaP2^6;//段选信号 sbit welaP2^7;//位选信号unsigned char num;//数码管显示的数字0~funsigned char code table[]{ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};//定义数码管显…

yakit使用教程(四,信息收集)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言&#xff1a;yakit下载安装教程。 一&#xff0c;基础爬虫。 在新建项目或新建临时项目后&#xff0c;点击安全工具&#xff0c;点击基础爬虫。 此工具并不是为了爬取网站上的一…

navicat下载教程(包会的)

目录 一、下载navicat安装包 步骤1---试用版本 步骤2---下载windws系统的navicat​编辑 步骤3---查看安装包 二、安装navicat 三、唤醒navicat 四、成功唤醒navicat 官网地址&#xff1a;Navicat | 下载 Navicat Premium 14 天免费 Windows、macOS 和 Linux 的试用版 …

【Power Compiler手册】15.多角多模式设计中的功耗优化

多角多模式设计中的功耗优化 可以使用多个运行条件和多种模式进行综合的设计被称为多角多模式设计。Design Compiler Graphical工具扩展了拓扑技术,以分析和优化这些设计。 有关多角多模式技术支持的综合工具的更多信息,请参见以下主题: • 优化多角多模式设计 • 报告命…