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.hqwc.cn/news/84817.html

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

相关文章

适应高速率网络设备的-2.5G/5G/10G网络变压器/网络滤波器介绍

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;在高速发展的互联网/物联网时代&#xff0c;为满足高网速的网络数据传输需求&#xff0c;网络设备在制造中也要选用合适的网络变压器/滤波器产品&#xff0c;有哪些可供选择的高速率网络变压器产品也是广大采购人员…

【Cortex-M3权威指南】学习笔记3 - 存储系统

目录 存储系统存储器映射存储器各种访问属性存储器的缺省访问许可位带操作非对齐数据传输互斥访问端模式 存储系统 存储器映射 CM3 预定义存储器映射简图&#xff08;CM3 的地址空间是 4GB &#xff09; 片上 SRAM&#xff1a;大小 512MB&#xff0c;拥有 1MB 位带区&#xff…

Vue3.0极速入门- 目录和文件说明

目录结构 以下文件均为npm create helloworld自动生成的文件目录结构 目录截图 目录说明 目录/文件说明node_modulesnpm 加载的项目依赖模块src这里是我们要开发的目录&#xff0c;基本上要做的事情都在这个目录里assets放置一些图片&#xff0c;如logo等。componentsvue组件…

LAMP配置与应用

目录 一、LAMP架构的组成 1、WEB资源类型 2、LAMP架构的组成 二、编译安装LAMP 编译安装apache 1、环境准备 2、导入apache相关压缩安装包&#xff0c;然后安装编译环境 3、解压软件包&#xff0c;并移动apr包与apr-util包到安装目录中&#xff0c;并切换到http解压出…

【Java并发】聊聊对象内存布局和syn锁升级过程

对象存储解析&#xff1a;一个空Object对象到底占据多少内存&#xff1f; 对象内存布局 Mark Word占用8字节&#xff0c;类型指针占用8个字节&#xff0c;对象头占用16个字节。 好了&#xff0c;我们来看一下一个Object对占用多少空间&#xff0c; 因为java默认是开启压缩…

前端需要理解的设计模式知识

设计模式的原则&#xff1a;1. 单一职责原则&#xff08;一个对象或方法只做一件事&#xff09; 2. 最少知识原则&#xff08;尽可能少的实体或对象间互相作用&#xff09; 3. 开放封闭原则&#xff08;软件实体具有可扩展且不可修改&#xff09; 设计模式是通过代码设计经验总…

【八股】2023秋招八股复习笔记4(MySQL Redis等)

文章目录 目录1、MySQLmysql索引实现mysql索引优化mysql索引失效的情况mysql 千万数据优化mysql 事务隔离级别 & 实现原理mysql MVCC版本链&#xff08;undo log&#xff09;mysql数据同步机制 & 主从复制 &#xff08;binlog&#xff09;mysql 日志&数据恢复&…

腾讯云服务器地域和可用区详细介绍_选择攻略

腾讯云服务器地域有什么区别&#xff1f;怎么选择比较好&#xff1f;地域选择就近原则&#xff0c;距离地域越近网络延迟越低&#xff0c;速度越快。关于地域的选择还有很多因素&#xff0c;地域节点选择还要考虑到网络延迟速度方面、内网连接、是否需要备案、不同地域价格因素…

量化QAT QLoRA GPTQ

模型量化的思路可以分为PTQ&#xff08;Post-Training Quantization&#xff0c;训练后量化&#xff09;和QAT&#xff08;Quantization Aware Training&#xff0c;在量化过程中进行梯度反传更新权重&#xff0c;例如QLoRA&#xff09;&#xff0c;GPTQ是一种PTQ的思路。 QAT…

spring整合mybatis教程(详细易懂)

一、引言 1、Spring整合MyBatis的目的是&#xff1f; 将两个框架结合起来&#xff0c;以实现更好的开发体验和效果。Spring提供了一种轻量级的容器和依赖注入的机制&#xff0c;可以简化应用程序的配置和管理。而MyBatis是一个优秀的持久层框架&#xff0c;可以方便地进行数据…

【面试题】MVC、MVP与MVVM模式是什么?

MVC模式 MVC是应用最广泛的软件架构之一&#xff0c;一般MVC分为&#xff1a; Model&#xff08; 模型 &#xff09;、Controller&#xff08; 控制器 &#xff09;、View&#xff08; 视图 &#xff09;。 这主要是基于分层的目的&#xff0c;让彼此的职责分开。View 一般…

自启动遇到某个节点或者某种环境变量问题导致启动失败

前言&#xff1a;此次记录无人车自启动过程遇到的问题。为了让ROS无人车能够实现飞控进行室外自主航线的问题&#xff0c;将飞控发布的PWM转为ROS无人车对应的速度。为了确保无人车启动后能够使用遥控器控制无人车&#xff0c;所以需要开机自启动。 硬件&#xff1a; 1、star…