• IO 多路复用


    IO 多路复用

    多路复用也是要用单线程来处理客户端并发,与其他模型相比多出了select这个模块。 程序不再直接问操作系统要数据,而是先发起一个select调用,select会阻塞直到其中某个socket准备就绪,此时应用程序再发起系统调用来获取数据,由于select已经帮我们确认了某个socket一定是就绪态,所以后续的recv,send,等操作可以立即完成,不会阻塞。简单的说,select相当于一个中间者,专门帮你看着socket,那个socket准备好了select就返回那个。
    你可以把select当做托儿所,把你的socket交给它来看管,当某个socket 要上厕所或者要吃饭的时候,select就会把它交给你。

    io多路复用

    用一个线程来并发处理所有的客户端

    原来我们是直接问操作系统要数据

      如果是io操作 没有数据就会进入阻塞状态

      非io操作 没有数据就会抛出异常,然后继续询问操作系统

    在多路复用模型中 要先问select模块 哪些socket已经准备就绪 然后在处理这些已经就绪的select,既然是已经就绪,那么执行recv,或是send 就不会再阻塞                                                                                                                select模块就只有select一个函数

    参数1:r_list需要被select检测是否是可读状态的客户端,把所有的socket放到该列表中,select会负责从中找出读取数据的socket

    参数2:w_list需要被select检测是否可写的客户端 把所有的socket,select会负责从中找到可以写入数据的socket

    参数3:x_list存储着要被检测异常条件。。。忽略即可

    返回一个元组 包含三个列表

    readables 已经处于可读状态的socket  即数据已经到达缓冲区

    writeables 已经处于可写的状态的socket 即缓冲区没满,可以发送

    从可读或可写的列表中拿出所有的socket 依次处理他们即可

    服务器:

    import socket

    import select 

    s = socket.socket()
    s.bind(("127.0.0.1",6666))
    s.listen()
    #在多路复用中 一旦交给select交给你一个socket一定意味着该socket已经准备就绪 可读或者可写

    r_list = []
    w_list =[]

    #存储需要发送的数据 以及对应的socket 把socket作为key 数据作为value
    data_dic = {}
    while True:
      readables,writeables,_ = select.select(r-_list,w_list,[])

      #接收数据以及服务器建立连接
      for i in readables:
        if i ==s:#如果是服务器 就执行accept
          c,addr = i.accept()
          r_list.append(i)
        else:#是一个客户端 那就recv收数据

          try ;

            data = i.recv(1024)

            #Linux中对方强行下线 或是Windows中正常下线
            if not data:
              i.close()
              r_list.remove(i)
              continue

            print(data)

      #发送数据  不清楚目前是否可以发送数据,所以交给select来检测
            w_list.append(i)

           #把要发送的数据先存着,等select告诉你这个连接可以发送时在发送

            data_dic[i]=data

        except ConnectionResetError:#Windows强行下线
            i.close()
            r_list.remove(i)#从检测列表中删除
      for i in writeables:

        try:

          i.send(data_dic[i].upper())#返回数据
          #data_dic.pop(i)
          #w_list.remove(i)

        except ConnectionResetError:#对面下线异常

          i.close()

        finally:

          data_dic.pop[i]
          w_list.remove(i)#从检测列表中删除

          

    #客户端

    import socket 

    c = socket.socket()
    c.connect((“127.0.0.1”,6666))
    print('connect....')
    while True:
      msg = input(">>>>").strip()
      if not msg:continue

      c.send(msg.encode.('utf-8')
      data = c.recv(1024)
      print(data.decode.('utf-8')

     

  • 相关阅读:
    python 函数的进阶
    python 函数的基础
    python3.6 中特殊格式化 和 字典中的pop
    python 文件操作
    python 基础数据类型补充,set集合,深浅拷贝
    python is 和 == 的区别,编码问题
    python字典
    python中堆和栈_Python小知识00002
    pip的更新_Python小知识00001
    Python字符串的编码
  • 原文地址:https://www.cnblogs.com/tangda/p/10519010.html
Copyright © 2020-2023  润新知