zoukankan      html  css  js  c++  java
  • Python IO多路复用select模块

    多路复用的分析实例:服务端、客户端

    #服务端配置
    from socket import *
    import time
    import select
    
    server = socket(AF_INET, SOCK_STREAM)
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)
    '''
    select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。
    当任何一个socket中的数据准备好了,select就会返回,会从操作系统将数据拷贝到应用程序中
    
    
    
    1.select.select(read_list,write_list,[],5)是由应用程序发起的,发送给操作系统,让操作系统去找有数据的套接字socket
        5:可以不用写,意思是5秒如果有数据连接进来会执行,如果没有回执行下一行代码(不用写是因为如果没数据执行下面的也没意义,
        能执行下面的代码,肯定是上面有数据过来已经成功建立了连接)
    
        重点:是没有数据过来才阻塞
              有数据过来会一直运行,不会阻塞
              
    2.异步IO:
        发送之后不用管,会自动把结果发给你,发一个给操作系统就不用管了(用于爬虫,效率最高)
        
        
        
    '''
    data_dic={} #设置一个空字典,目的是用于将conn:data 一一绑定
    read_list=[server,]   #放和收消息有关的套接字 conn.recv()  server.accept(),是被检测的一些套接字
    write_list=[]   #send写数据,存放建立好的一些套接字服务端
    print('start....')
    while True:
        #select执行的返回结果是维护的列表里面,哪个有数据过来了
        rl,wl,xl=select.select(read_list,write_list,[])  #这里select在指定的时间段内不停的去问操作系统要数据,如果没有数据就会执行下面一行代码
        print(read_list) #read_list=[server,conn1,conn2,conn3,conn4]
        print(rl,len(rl))     #重点理解:上面循环每次得到r1只时包换操作系统询问到的有数据的套接字[conn1,conn2..]
        #r1就是select返回的有
        # print('read_list:%s rl:%s wl:%s ' %(len(read_list),len(rl),len(wl))) #rl=[conn1,conn2]
    
    #注意:
    
        #1.刚开始循环r1里面只有server,read_list=[server]里面也只有server,此时r1和read_list里面内筒一样
        #2.刚开始read_list=[server,conn] server是负责建立新连接的,conn是负责收消息的
    
        #3.当服务端accept()收到新的连接并加入到read_list[server,conn]里面,
        # 问到结果之后此时 rl,wl,xl=select.select(read_list,write_list,[]),得到的r1里面只包含已经有数据过来的连接
    
        #read_list里面的连接请求不会取走,只要有数据就不会阻塞,阻塞的情况是列表里面没有数据拿
        #r1里面去依次for循环取数据,如果是server套接字对象就是accept(),否则就负责recv()数据
        for sk in rl:   #初始状态read_list里面放的的是server套接字,需要执行accept操作
            if sk == server:     #判断for循环,首先只有server服务端负责accept()接收
                conn,addr=sk.accept()
                read_list.append(conn)   #后面并发的数量多了时要往read_list里面放一些有数据的套接字对象
            else:
                # sk.recv(1024)
                # print(sk)
                data=sk.recv(1024)
                write_list.append(sk)  #有消息往外回所以加进去了
                data_dic[sk]=data  #制作字典绑定send的对象和数据:格式为发送的对象conn:对应发送的数据 data
    
                #因为conn占用了应用程序的资源、对应操作系统还有维持连接
    
        for sk in wl:
            sk.send(data_dic[sk].upper())   #根据字典里面对应的socket套接字对象拿到,拿到
            data_dic.pop(sk)  #发完之后字典里面就没必要存放消息了,所以就回收
            write_list.remove(sk) #回完之后没有了,所以就删除
    
            #write_list还没满的情况下会返回w1
            #read_list占应用程序的资源
    
            # 因为conn占用了应用程序的资源、对应操作系统还要维持链接
    #客户端配置
    from socket import *
    import os
    
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(('127.0.0.1',8080))
    
    while True:
        msg=input('输入要操作的命令:')
        client.send(msg.encode('utf-8'))
        data=client.recv(1024)
        print(data.decode('utf-8'))
  • 相关阅读:
    深度学习中的激活函数
    23.从上往下打印二叉树
    22.栈的压入、弹出序列
    使用TensorFlow实现DNN
    shell按行读取文件
    linux集群批量执行命令
    CDH升级
    自动微分方法(auto diff)
    快速了解负载均衡
    拼写纠错的利器,BK树算法
  • 原文地址:https://www.cnblogs.com/yangzhizong/p/9334772.html
Copyright © 2011-2022 走看看