python网络编程

文章目录

    • socket套接字
    • 客户端/服务模型
    • linux文件描述符fd
    • Linux网络IO模型详解
    • 网络服务器Apache VS Nginx
    • 生产者消费者-生成器版
    • 客户端/服务端-多线程版
    • IO多路复用TCPServer模型
    • 异步IO多路复用TCPServer模型

socket套接字

  • 套接字(socket)是抽象概念,表示TCP连接的一端

  • 通过套接字可以进行数据发送或接收 {IP:Port}==>> 套接字

  • TCP连接由两个套接字组成
    ={Socket1:Socket2}
    ={IP:Port}{IP:Port}

客户端/服务模型

在这里插入图片描述

linux文件描述符fd

Linux一切皆是文件,文件类型 socket.socket.fileno()

  • 普通文件

  • 目录文件

  • 符号链接

  • 设备文件

  • 套接字

    • 进程级的文件描述符表 :文件
    • 系统级的文件描述符表 :外设
    • 文件系统的i-Node表:目录
  • FIFO

Linux网络IO模型详解

阻塞式IO

在这里插入图片描述

非阻塞式IO

在这里插入图片描述

IO多路复用

在这里插入图片描述

信号驱动式IO

在这里插入图片描述

异步IO

在这里插入图片描述

五种IO比较

在这里插入图片描述

IO多路复用

在这里插入图片描述

  • select:线性扫描所有监听的文件描述符fd

  • poll:同选择性能有所优化

  • Epoll:使用红黑树管理数据结构,性能好

网络服务器Apache VS Nginx

ApacheNginx
多线程多路复用
资源占用大更加轻量
模块多模块化设计,社区活跃
稳定,缺陷少静态资源、反向代理
性能较好性能很好

生产者消费者-生成器版

import time# 消费者
def consumer():cnt = yieldwhile True:if cnt <= 0:# 暂停、让出CPUcnt = yield cntcnt -= 1time.sleep(1)print('consumer consum 1 cnt. cnt =', cnt)# 生产者 (调度器)
def producer(cnt):gen = consumer()# 激活生成器next(gen)gen.send(cnt)while True:cnt += 1print('producer producer 5 cnt. cnt =', cnt)# 调度消费者current = int(time.time())if current % 5 == 0:cnt = gen.send(cnt)else:time.sleep(1)if __name__ == '__main__':producer(0)

客户端/服务端-多线程版

客户端

# -*- encoding=utf-8 -*-
# 客户端import socketclient = socket.socket()
print('client.fileno:', client.fileno())client.connect(('127.0.0.1', 8999))while True:content = str(input('>>>'))client.send(content.encode())content = client.recv(1024)print('client recv content:', content)

服务端

import socket
import threadingdef thread_process(s):while True:content = s.recv(1024)if len(content) == 0:breaks.send(content.upper())print(str(content, encoding='utf-8'))  # 接受来自客户端的消息,并打印出来s.close()server = socket.socket()  # 1. 新建socket
server.bind(('127.0.0.1', 8999))  # 2. 绑定IP和端口(其中127.0.0.1为本机回环IP)
server.listen(5)  # 3. 监听连接while True:s, addr = server.accept()  # 4. 接受连接new_thread = threading.Thread(target=thread_process, args=(s,))print('new thread process connect addr:{}'.format(addr))new_thread.start()

IO多路复用TCPServer模型

# -*- encoding=utf-8 -*-
# IO多路复用TCPServer模型import select
import socketdef serve():server = socket.socket()server.bind(('127.0.0.1', 8999))server.listen(1)epoll = select.epoll()epoll.register(server.fileno(), select.EPOLLIN)connections = {}contents = {}while True:events = epoll.poll(10)for fileno, event in events:if fileno == server.fileno():# 当fd为当前服务器的描述符时,获取新连接s, addr = server.accept()  # 获取套接字和地址print(f"new connection from addr:{addr},fileno:{s.fileno()},socket:{s}")epoll.register(s.fileno(), select.EPOLLIN)connections[s.fileno()] = selif event == select.EPOLLIN:# 当fd不为服务器描述符为客户端描述符时,读事件就绪,有新数据可读s = connections[fileno]content = s.recv(1024)if content:# 当客户端发送数据时print(f"recv content is {content}")print(f"fileno:{fileno} event:{event}")epoll.modify(fileno, select.EPOLLOUT)contents[fileno] = contentelse:# 当客户端退出连接时print(f"recv content is null")print(f"fileno;{fileno} event:{event} ")epoll.unregister(fileno)s.close()connections.pop(fileno)elif event == select.EPOLLOUT:# 当fd不为服务器描述符为客户端描述符时,写事件就绪try:content = contents[fileno]s = connections[fileno]s.send(content)epoll.modify(s.fileno(), select.EPOLLIN)print(f"modify content is {content}")print(f"fileno;{fileno} event:{event} ")except Exception as error:epoll.unregister(fileno)s.close()connections.pop(fileno)contents.pop(fileno)print(f"modify content is failed")print(f"fileno;{fileno} event:{event} ")if __name__ == '__main__':serve()

异步IO多路复用TCPServer模型

import socket
import select
from collections import dequeclass Future:"""可等待对象 Future"""def __init__(self, loop):self.loop = loopself.done = Falseself.co = Nonedef set_done(self):self.done = Truedef set_coroutine(self, co):self.co = codef __await__(self):if not self.done:yield selfreturnclass EventLoop:"""调度器:epoll事件驱动"""current = Nonerunnable = deque()epoll = select.epoll()handler = {}@classmethoddef instance(cls):if not EventLoop.current:EventLoop.current = EventLoop()return EventLoop.currentdef create_future(self):return Future(loop=self)def register_handler(self, fileno, events, handler):self.handler[fileno] = handlerself.epoll.register(fileno, events)def unregister_handler(self, fileno):self.epoll.unregister(fileno)self.handler.pop(fileno)def add_coroutine(self, co):self.runnable.append(co)def run_coroutine(self, co):try:future: Future = co.send(None)future.set_coroutine(co)except Exception as e:print(e)print('coroutine {} stopped'.format(co.__name__))def run_forever(self):while True:while self.runnable:self.run_coroutine(co=self.runnable.popleft())events = self.epoll.poll(1)for fileno, event in events:handler = self.handler.get(fileno)handler()class SocketWrapper:"""套接字协程适配器"""def __init__(self, sock: socket.socket, loop: EventLoop):self.loop = loopself.sock = sockself.sock.setblocking(False)@propertydef fileno(self):return self.sock.fileno()def create_future_for_events(self, events):future: Future = self.loop.create_future()def handler():future.set_done()self.loop.unregister_handler(self.fileno)if future.co:self.loop.add_coroutine(future.co)self.loop.register_handler(self.fileno, events, handler)return futureasync def accept(self):while True:try:sock, addr = self.sock.accept()return SocketWrapper(sock, self.loop), addrexcept BlockingIOError:future = self.create_future_for_events(select.EPOLLIN)await futureasync def recv(self, backlog):while True:try:return self.sock.recv(backlog)except BlockingIOError:future = self.create_future_for_events(select.EPOLLIN)await futureasync def send(self, data):while True:try:return self.sock.send(data)except BlockingIOError:future = self.create_future_for_events(select.EPOLLOUT)await futureclass TCPServer:def __init__(self, loop: EventLoop):self.loop = loopself.listen_sock: SocketWrapper = self.create_listen_socket()self.loop.add_coroutine(self.serve_forever())def create_listen_socket(self, ip='localhost', port=8999):sock = socket.socket()sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.bind((ip, port))sock.listen()return SocketWrapper(sock, self.loop)async def handler_client(self, sock:SocketWrapper):while True:data = await sock.recv(1024)if not data:print('client disconnected')breakawait sock.send(data.upper())async def serve_forever(self):while True:sock, addr = await self.listen_sock.accept()print(f'client connect addr = {addr}')self.loop.add_coroutine(self.handler_client(sock))if __name__ == '__main__':loop = EventLoop.instance()server = TCPServer(loop)loop.run_forever()

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

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

相关文章

c++ qt--事件(第六部分)

c qt–事件&#xff08;第六部分&#xff09; 一.编辑伙伴&#xff0c;编辑顺序&#xff08;按TAB进行切换&#xff09; 1.编辑伙伴 此功能在设计界面如下的位置 1.设置伙伴关系 鼠标左键长按一个Label组件然后把鼠标移到另一个组件上 2.伙伴关系的作用 伙伴关系的作用就是…

HoudiniVex笔记_P26_RecursionBasics递归基础

原视频&#xff1a;https://www.youtube.com/playlist?listPLzRzqTjuGIDhiXsP0hN3qBxAZ6lkVfGDI Bili&#xff1a;Houdini最强VEX算法教程 - VEX for Algorithmic Design_哔哩哔哩_bilibili Houdini版本&#xff1a;19.5 1、概述 递归是一种直接或者间接地调用自身的算法&a…

猜数游戏-Rust版

cargo new guessing_game 创建项目 输入任意内容&#xff0c;并打印出来 main.rs: use std::io; // 像String这些类型都在预先导入的prelude里&#xff0c;如果要使用的不在prelude里&#xff0c;则需要显式导入fn main() { println!("猜数"); println!("…

37、springboot 为 spring mvc 提供的自动配置及对自动配置的一些自定义定制(大体思路)

springboot 为 spring mvc 提供的自动配置及对自动配置的一些自定义定制&#xff08;大体思路&#xff09; ★ Spring Boot主流支持两个MVC框架&#xff1a; Spring MVC&#xff08;基于Servlet&#xff09; Spring WebFlux&#xff08;基于Reactive&#xff0c;属于响应式AP…

vcomp140.dll丢失的修复方法分享,电脑提示vcomp140.dll丢失修复方法

今天&#xff0c;我的电脑出现了一个奇怪的问题&#xff0c;打开某些程序时总是提示“找不到vcomp140.dll文件”。这个问题让我非常头疼&#xff0c;因为我无法正常使用电脑上的一些重要软件。为了解决这个问题&#xff0c;我在网上查找了很多资料&#xff0c;并尝试了多种方法…

使用Aircrack-ng进行无线网络破解

Aircrack-ng是一款流行的无线网络渗透测试工具&#xff0c;主要用于密码破解和网络分析。但是&#xff0c;请注意&#xff0c;仅在有合法授权的情况下使用这些工具。 以下是一个使用Aircrack-ng进行无线网络破解的示例&#xff0c;以及一些步骤和注意事项&#xff1a; 步骤&a…

2023年最新版Windows环境下|Java8(jdk1.8)安装教程

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 jdk1.8的下载和使用总共分为3个步骤&#xff1a; jdk1.8的下载、jdk1.8的安装、配置环境变量。 目录 一、jdk1.8下载…

IDEA常用配置之类Tab页多行显示

文章目录 IDEA常用配置之类Tab页多行显示 IDEA常用配置之类Tab页多行显示 默认在Idea中打开类过多&#xff0c;后面会隐藏显示&#xff0c;这里修改配置&#xff0c;将类设置为多行显示&#xff0c;方便查找已经打开的类 修改后显示样式

Unity——后期处理举例

Post Processing&#xff08;后期处理&#xff09;并不属于特效&#xff0c;但现代的特效表现离不开后期处理的支持。本文以眩光&#xff08;Bloom&#xff09;为例&#xff0c;展示一种明亮的激光的制作方法 1、安装后期处理扩展包 较新的Unity版本已经内置了新版的后期处理扩…

创建型模式-建造者模式

使用多个简单的对象一步一步构建成一个复杂的对象 主要解决&#xff1a;主要解决在软件系统中&#xff0c;有时候面临着"一个复杂对象"的创建工作&#xff0c;其通常由各个部分的子对象用一定的算法构成&#xff1b;由于需求的变化&#xff0c;这个复杂对象的各个部…

ARM DIY(三)板载串口和 LCD 调试

前言 今天焊接两大关键输入输出设备&#xff1a;串口和屏幕。 串口 串口部分使用 CP2102N 芯片&#xff08;USB 转 TTL&#xff09;&#xff0c;这样用一根数据线连接板子和 PC 就可以直接调试了。 焊接 CP2102 和 Type C 上电调试&#xff0c;串口可以正常输入输出。 看来…

使用Python写入数据到Excel:实战指南

在数据科学领域&#xff0c;Excel是一种广泛使用的电子表格工具&#xff0c;可以方便地进行数据管理和分析。然而&#xff0c;当数据规模较大或需要自动化处理时&#xff0c;手动操作Excel可能会变得繁琐。此时&#xff0c;使用Python编写程序将数据写入Excel文件是一个高效且便…

【办公类-16-01-02】2023年度上学期“机动班下午代班的排班表——跳过周三、节日和周末”(python 排班表系列)

背景需求&#xff1a; 2023年第一学期&#xff08;2023年9-2024年1月&#xff09;&#xff0c;我又被安排为“机动班”&#xff0c;根据新学期的校历&#xff0c;手动推算本学期的机动班的带班表 排版原则 1、班级数量&#xff1a;共有6个班级&#xff0c;循环滚动 2、每周次…

安装启动yolo5教程

目录 一、下载yolo5项目 二、安装miniconda&#xff08;建议不要安装在C盘&#xff09; 三、安装CUDA 四、安装pytorch 五、修改配置参数 六、修改电脑参数 七、启动项目 博主硬件&#xff1a; Windows 10 家庭中文版 一、下载yolo5项目 GitHub - ultralytics/yolov5:…

使用EF Core更新与修改生产数据库

使用EF Core的Code First&#xff0c;在设计阶段&#xff0c;直接使用Database.EnsureCreated()和EnsureDeleted()可以快速删除、更新最新的数据结构。由于没有什么数据&#xff0c;删除的风险非常低。但是对于已经投入生产的数据库&#xff0c;这个方法就绝对不可行了。 考虑…

【C进阶】指针(一)

大家好&#xff0c;我是深鱼~ 【前言】&#xff1a; 指针的主题&#xff0c;在初阶指针章节已经接触过了&#xff0c;我们知道了指针的概念&#xff1a; 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址的唯一标识一块内存空间&#xff08;指针变量&#xff09;&a…

集丰照明|汽车美容店设计,装修色彩灯光搭配方法

正确处理好店面的空间设计。 店铺各个功能区设计要合理&#xff0c;衔接合理&#xff0c;这样既能提高员工的工作效率也能提高顾客的满意度。合理安排店铺的空间分配&#xff0c; 要给顾客一种舒适度&#xff0c;既不能让顾客感觉到过于拥挤&#xff0c;又不能浪费店铺的有限空…

.NET Core 实现日志打印输出在控制台应用程序中

在本文中&#xff0c;我们将探讨如何在 .NET Core 应用程序中将日志消息输出到控制台&#xff0c;从而更好地了解应用程序的运行状况。 .NET Core 实现日志打印输出在控制台应用程序中 在 .NET Core 中&#xff0c;日志输出打印是使用 Microsoft.Extensions.Logging 命名空间…

【LeetCode-面试经典150题-day14】

目录 19.删除链表的倒数第N个结点 82.删除排序链表中的重复元素Ⅱ 61. 旋转链表 86.分隔链表 146.LRU缓存 19.删除链表的倒数第N个结点 题意&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 【输入样例】head [1,2,3,4,5…

element-ui里el-table表格操作列多横线怎么解决

错误展示 错误原因 在vue中封装了element-ui表格&#xff0c;然后使用插槽&#xff0c;fixed定位等&#xff0c;导致样式出现了错乱 解决方案 1、线没有对齐 /* Element-UI 的table 组件出现表格线条不对齐的问题 */ body .el-table th.gutter {display: table-cell !impor…