IO多路复用

IO多路复用

1. 定义
同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件。以此形成可以同时处理多个IO
的行为,避免一个IO阻塞造成其他IO均无法执行,提高了IO执行效率。
2. 具体方案
select方法 : windows linux unix
poll方法: linux unix
epoll方法: linux
select 方法
代码实现: day10/select_server.py
rs, ws, xs=select(rlist, wlist, xlist[, timeout])
功能: 监控IO事件,阻塞等待IO发生
参数:rlist 列表 读IO列表,添加等待发生的或者可读的IO事件
wlist 列表 写IO列表,存放要可以主动处理的或者可写的IO事件
xlist 列表 异常IO列表,存放出现异常要处理的IO事件
timeout 超时时间

返回值: rs 列表 rlist中准备就绪的IO
ws 列表 wlist中准备就绪的IO
xs 列表 xlist中准备就绪的IO

select 实现tcp服务

【1】将关注的IO放入对应的监控类别列表
【2】通过select函数进行监控
【3】遍历select返回值列表,确定就绪IO事件
【4】处理发生的IO事件

"""
select tcp服务
重点代码
【1】将关注的IO放入对应的监控类别列表
【2】通过select函数进行监控
【3】遍历select返回值列表,确定就绪IO事件
【4】处理发生的IO事件
"""
from socket import *
from select import select

# 创建监听套接字,作为关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,
             SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(3)

# 设置关注的IO
rlist = [s] # s的读IO行为
wlist = []
xlist = []

while True:
    # 循环监控s
    rs,ws,xs = select(rlist,wlist,xlist)
    for r in rs:
        if r is s:
            # 又有新的客户端链接
            c, addr = r.accept()
            print("Connect from", addr)
            rlist.append(c)
        else:
            # 某个客户端给我发消息
            data = r.recv(1024).decode()
            if not data:
                # 客户端断开
                rlist.remove(r) # 不再关注这个IO
                r.close()
                continue
            print(data)
            # r.send(b'OK')
            wlist.append(r) #加入写IO

    for w in ws:
        w.send(b'OK')
        wlist.remove(w)














注意
wlist中如果存在IO事件,则select立即返回给ws
处理IO过程中不要出现死循环占有服务端的情况
IO多路复用消耗资源较少,效率较高

@@扩展: 位运算

定义 : 将整数转换为二进制,按二进制位进行运算
运算符号:
& 按位与
| 按位或
^ 按位异或
<< 左移
>>右移
e.g. 14 --> 01110

19 --> 10011
14 & 19 = 00010 = 2 一0则0
14 | 19 = 11111 = 31 一1则1
14 ^ 19 = 11101 = 29 相同为0不同为1
14 << 2 = 111000 = 56 向左移动低位补0
14 >> 2 = 11 = 3 向右移动去掉低位

poll方法

代码实现: day10/poll_server.py
p = select.poll()
功能 : 创建poll对象
返回值: poll对象

p.register(fd,event)
功能: 注册关注的IO事件
参数:fd 要关注的IO
event 要关注的IO事件类型
常用类型:POLLIN 读IO事件(rlist)
POLLOUT 写IO事件 (wlist)
POLLERR 异常IO (xlist)
POLLHUP 断开连接
e.g. p.register(sockfd,POLLIN|POLLERR)

p.unregister(fd)
功能:取消对IO的关注
参数:IO对象或者IO对象的fileno

events = p.poll()
功能: 阻塞等待监控的IO事件发生
返回值: 返回发生的IO
events格式 [(fileno,event),()…]
每个元组为一个就绪IO,元组第一项是该IO的fileno,第二项为该IO就绪的事件类型

poll_server 步骤

【1】 创建套接字
【2】 将套接字register
【3】 创建查找字典,并维护
【4】 循环监控IO发生
【5】 处理发生的IO

"""
poll_server.py  tcp服务
重点代码

思路: poll() 的返回值不是IO对象
      建立字典 {fileno:io_obj}
"""
from socket import *
from select import *

# 创建监听套接字,作为关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,
             SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(3)

# 创建poll对象
p = poll()

# 建立查找字典
fdmap = {s.fileno():s}

# 关注s套接字
p.register(s,POLLIN)

# 循环监控IO发生
while True:
    # 提交监控
    events = p.poll()
    print(events)
    for fd,event in events:
        if fd == s.fileno():
            c,addr = s.accept()
            print("Connect from",addr)
            p.register(c,POLLIN|POLLERR) # 添加新的关注IO
            fdmap[c.fileno()] = c  # 注意维护字典与register保持一致
        elif event & POLLIN:
            # 通过文件描述符取得对象
            data = fdmap[fd].recv(1024).decode()
            if not data:
                p.unregister(fd) # 不再关注
                fdmap[fd].close()
                del fdmap[fd] # 从字典删除
                continue
            print(data)
            fdmap[fd].send(b'OK')

epoll方法

代码实现: day10/epoll_server.py

  1. 使用方法 : 基本与poll相同
    生成对象改为 epoll()
    将所有事件类型改为EPOLL类型
  2. epoll特点
    epoll 效率比select poll要高
    epoll 监控IO数量比select要多
    epoll 的触发方式比poll要多 (EPOLLET边缘触发)
from socket import *
from select import *

# 创建监听套接字,作为关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,
             SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(3)

# 创建epoll对象
p = epoll()

# 建立查找字典
fdmap = {s.fileno():s}

# 关注s套接字
p.register(s,EPOLLIN)

# 循环监控IO发生
while True:
    # 提交监控
    events = p.poll()
    print("你有新的IO需要处理哦")
    for fd,event in events:
        if fd == s.fileno():
            c,addr = s.accept()
            print("Connect from",addr)
            # 添加新的关注IO
            p.register(c,EPOLLIN|EPOLLERR|EPOLLET)  # 边缘触发
            fdmap[c.fileno()] = c  # 注意维护字典与register保持一致
        # elif event & EPOLLIN:
        #     # 通过文件描述符取得对象
        #     data = fdmap[fd].recv(1024).decode()
        #     if not data:
        #         p.unregister(fd) # 不再关注
        #         fdmap[fd].close()
        #         del fdmap[fd] # 从字典删除
        #         continue
        #     print(data)
        #     fdmap[fd].send(b'OK')

HTTPServer v2.0

day10/http_server.py

  1. 主要功能 :
    【1】 接收客户端(浏览器)请求
    【2】 解析客户端发送的请求
    【3】 根据请求组织数据内容
    【4】 将数据内容形成http响应格式返回给浏览器
  2. 升级点 :
    【1】 采用IO并发,可以满足多个客户端同时发起请求情况
    【2】 通过类接口形式进行功能封装
    【3】 做基本的请求解析,根据具体请求返回具体内容,同时处理客户端的非网页请求行为
"""
httpserver 2.0
"""
from socket import *
from select import select

class HTTPServer:
    def __init__(self,host='0.0.0.0',port=80,dir=None):
        self.host = host
        self.port = port
        self.address = (host,port)
        self.dir = dir
        self.rlist = []
        self.wlist = []
        self.xlist = []
        # 直接创建套接字
        self.create_socket()

    # 创建套接字
    def create_socket(self):
        self.sockfd = socket()
        self.sockfd.setsockopt(SOL_SOCKET,
                               SO_REUSEADDR,
                               1)
        self.sockfd.bind(self.address)

    # 启动服务
    def serve_forever(self):
        self.sockfd.listen(3)
        print("Listen the port %d"%self.port)
        # IO多路服用方法监控IO
        self.rlist.append(self.sockfd)
        while True:
            rs,ws,xs=select(self.rlist,
                            self.wlist,
                            self.xlist)
            for r in rs:
                if r is self.sockfd:
                    # 浏览器链接
                    c,addr = r.accept()
                    self.rlist.append(c)
                else:
                    # 处理具体请求
                    self.handle(r)

    # 处理客户端请求
    def handle(self,connfd):
        request = connfd.recv(4096).decode()
        # 客户端断开
        if not request:
            self.rlist.remove(connfd)
            connfd.close()
            return

        # 解析请求,提取请求内容
        request_line = request.split('\n')[0]
        info = request_line.split(' ')[1]
        print(connfd.getpeername(),':',info)

        # 根据请求内容将其分为两类
        if info == '/' or info[-5:] == '.html':
            self.get_html(connfd,info)
        else:
            self.get_data(connfd,info)
        connfd.close()
        self.rlist.remove(connfd)

    def get_data(self,connfd,info):
        response = "HTTP/1.1 200 OK\r\n"
        response += "Content-Type:text/html\r\n"
        response += '\r\n'
        response += "<h1>Waiting for httpserver 3.0</h1>"
        connfd.send(response.encode())
    # 处理网页
    def get_html(self,connfd,info):
        if info == '/':
            # 要主页
            filename = self.dir+'/index.html'
        else:
            # 具体的网页
            filename = self.dir + info
        try:
            fd = open(filename)
        except Exception:
            response = "HTTP/1.1 404 Not Found\r\n"
            response += "Content-Type:text/html\r\n"
            response += '\r\n'
            response += "<h1>Sorry....</h1>"
        else:
            response = "HTTP/1.1 200 OK\r\n"
            response += "Content-Type:text/html\r\n"
            response += '\r\n'
            response += fd.read()
        finally:
            # 将响应发送给浏览器
            connfd.send(response.encode())

if __name__ == '__main__':
    # 通过HTTPServer类快速搭建服务
    # 通过该服务让浏览器访问到我的网页
    # 1. 使用流程
    # 2. 需要用户确定的内容

    # 用户决定的参数
    HOST = '0.0.0.0'
    PORT = 8000
    DIR = './static'
    httpd = HTTPServer(HOST,PORT,DIR) # 生成对象
    httpd.serve_forever() # 启动服务
【电力系统】单机无穷大电力系统短路故障暂态稳定Simulink仿真(带说明文档)内容概要:本文档围绕“单机无穷大电力系统短路故障暂态稳定Simulink仿真”展开,提供了完整的仿真模型与说明文档,重点研究电力系统在发生短路故障后的暂态稳定性问题。通过Simulink搭建单机无穷大系统模型,模拟不同类型的短路故障(如三相短路),分析系统在故障期间及切除后的动态响应,包括发电机转子角度、转速、电压和功率等关键参数的变化,进而评估系统的暂态稳定能力。该仿真有助于理解电力系统稳定性机理,掌握暂态过程分析方法。; 适合人群:电气工程及相关专业的本科生、研究生,以及从事电力系统分析、运行与控制工作的科研人员和工程师。; 使用场景及目标:①学习电力系统暂态稳定的基本概念与分析方法;②掌握利用Simulink进行电力系统建模与仿真的技能;③研究短路故障对系统稳定性的影响及提高稳定性的措施(如故障清除时间优化);④辅助课程设计、毕业设计或科研项目中的系统仿真验证。; 阅读建议:建议结合电力系统稳定性理论知识进行学习,先理解仿真模型各模块的功能与参数设置,再运行仿真并仔细分析输出结果,尝试改变故障类型或系统参数以观察其对稳定性的影响,从而深化对暂态稳定问题的理解。
本研究聚焦于运用MATLAB平台,将支持向量机(SVM)应用于数据预测任务,并引入粒子群优化(PSO)算法对模型的关键参数进行自动调优。该研究属于机器学习领域的典型实践,其核心在于利用SVM构建分类模型,同时借助PSO的全局搜索能力,高效确定SVM的最优超参数配置,从而显著增强模型的整体预测效能。 支持向量机作为一种经典的监督学习方法,其基本原理是通过在高维特征空间中构造一个具有最大间隔的决策边界,以实现对样本数据的分类或回归分析。该算法擅长处理小规模样本集、非线性关系以及高维度特征识别问题,其有效性源于通过核函数将原始数据映射至更高维的空间,使得原本复杂的分类问题变得线性可分。 粒子群优化算法是一种模拟鸟群社会行为的群体智能优化技术。在该算法框架下,每个潜在解被视作一个“粒子”,粒子群在解空间中协同搜索,通过不断迭代更新自身速度与位置,并参考个体历史最优解和群体全局最优解的信息,逐步逼近问题的最优解。在本应用中,PSO被专门用于搜寻SVM中影响模型性能的两个关键参数——正则化参数C与核函数参数γ的最优组合。 项目所提供的实现代码涵盖了从数据加载、预处理(如标准化处理)、基础SVM模型构建到PSO优化流程的完整步骤。优化过程会针对不同的核函数(例如线性核、多项式核及径向基函数核等)进行参数寻优,并系统评估优化前后模型性能的差异。性能对比通常基于准确率、精确率、召回率及F1分数等多项分类指标展开,从而定量验证PSO算法在提升SVM模型分类能力方面的实际效果。 本研究通过一个具体的MATLAB实现案例,旨在演示如何将全局优化算法与机器学习模型相结合,以解决模型参数选择这一关键问题。通过此实践,研究者不仅能够深入理解SVM的工作原理,还能掌握利用智能优化技术提升模型泛化性能的有效方法,这对于机器学习在实际问题中的应用具有重要的参考价值。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值