39.IO多路复用(用select实现伪并发)

IO多路复用

1.用select实现多端口被多客户端访问的多路复用伪并发

  IO多路复用服务端:既读又写

# IO多路复用实现伪并发   用多个IO,可以监听多个文件句柄(socket对象)(一般是可以读了或者可以写了),
# 一旦文件句柄出现变化,就可以感应到
# 对于原生的socket  只能处理一个请求,只能监听一个端口
# 1.如何让server端监听两个端口
import socket

sk1 = socket.socket()
sk1.bind((‘127.0.0.1‘, 8001,))
sk1.listen()

sk2 = socket.socket()
sk2.bind((‘127.0.0.1‘, 8002,))
sk2.listen()

sk3 = socket.socket()
sk3.bind((‘127.0.0.1‘, 8003,))
sk3.listen()

inputs = [sk3, sk1, sk2, ]

import select
# select,内部c语言实现,for循环监听多个句柄 最大1024个(window上只支持select)
# poll,内部依然用for循环检测无限制
# epool内部使用异步(谁有变化,谁告诉我,不一个一个去问),内部让每个句柄发生变化的时候去告知epoll,不用循环

while True:
    r_list, w_list, e_list = select.select(inputs, [], [], 1)
    ‘‘‘
    检测句柄变化
    参数1:1为等待时间  1s后进去下次循环
    第三个参数:感知句柄错误,从inputs传到e_list,并将错误句柄从第一个参数中去除,程序就不会发生错误
    第二个参数:参数中的值,均会传到w_list,无论其是否发生变化
    第一个参数:检测句柄变化,inputs中谁变化就将其放入r_list
    ‘‘‘
    # [sk3, sk1, sk2]  内部自动监听sk3,sk1, sk2三个对象,一旦某个句柄发生变化
    # 如果有人来连sk3,r_list = [sk]接收客户端的请求
    # 如果有人来连sk1,r_list = [sk1]接收客户端的请求
    for sk in r_list:
        # 每一个连接对象
        conn, address = sk.accept()
        conn.sendall(bytes(‘hello‘,encoding=‘utf-8‘))
        conn.close()

  客户端1:

import socket

obj = socket.socket()

obj.connect((‘127.0.0.1‘,8001,))

content = str(obj.recv(1024),encoding=‘utf-8‘)

print(content)

obj.close()

  客户端2:

import socket

obj = socket.socket()

obj.connect((‘127.0.0.1‘,8002,))

content = str(obj.recv(1024),encoding=‘utf-8‘)

print(content)

obj.close()

2.用select实现,多个客户端的不同端口访问服务器的某一端口的伪并发,读写分离

  服务端:

import socket

sk1 = socket.socket()
sk1.bind((‘127.0.0.1‘, 8001,))
sk1.listen()

inputs = [sk1, ]
outputs = []  # outputs的内容将会一直存在于w_list中
message = {}

import select

# select监听socket对象,一旦socket变换就能感知到
‘‘‘
服务端:
sk1 =socket.socket()
conn, address = sk1.accept()
conn.recv(1024)
客户端:
sk1 = socket.socket()
sk1.sendall()

在服务端对象sk1只负责接收用户的连接

而conn才负责专门与每一个客户端的sk1对象通信

‘‘‘

while True:
    # 如果有人连接sk1
    # r_list = [sk1,]
    # 如果有人第一次连接,sk1发生变化
    r_list, w_list, e_list = select.select(inputs, outputs, inputs, 1)
    print(‘正在监听的socket对象%d‘ % len(inputs))
    print(r_list)

    for sk1_or_conn in r_list:
        # 每一个连接对象
        if sk1_or_conn == sk1:
            # 表示有新用户来连接
            conn, address = sk1_or_conn.accept()
            inputs.append(conn)  # inputs = [sk1,conn]
            message[conn] = []
        else:
            try:  # 有老用户发消息了
                ‘‘‘
                2.7中,客户端断开连接,服务器会接收到空字符串
                3.6中,断开后,服务器会报错
                ‘‘‘
                data_bytes = sk1_or_conn.recv(1024)
            except Exception as ex:
                inputs.remove(sk1_or_conn)
                # 从inputs中移除,不再联系
            else:
                data_str = str(data_bytes, encoding=‘utf-8‘)
                outputs.append(sk1_or_conn)  #w_list记录哪个客户端跟服务器发送过消息
                message[sk1_or_conn].append(data_str )

# 本质上还是一个一个处理。只是事情一发生即可处理而已
# select的难点在于它的第一个参数,既放了服务端的socket对象,
                # 还放了客户端与服务端的通道对象conn

    # w_list仅仅保存了谁给我发过消息
    for conn in w_list:
        recv_str = message[conn][0]
        del message[conn][0]
        conn.sendall(bytes(recv_str + ‘好‘, encoding=‘utf-8‘))
        outputs.remove(conn)

  客户端:(在python中按快捷键shift+crtl+F10模拟不同的客户端)  

import socket

obj = socket.socket()
obj.connect((‘127.0.0.1‘, 8001,))

while True:
    inp = input(‘>>>‘)
    obj.sendall(bytes(inp, encoding=‘utf-8‘))
    ret = str(obj.recv(1024), encoding=‘utf-8‘)
    print(ret)

  

  

  

  

时间: 2024-09-29 16:38:51

39.IO多路复用(用select实现伪并发)的相关文章

网络通信 --> IO多路复用之select、poll、epoll详解

IO多路复用之select.poll.epoll详解 目前支持I/O多路复用的系统调用有 select,pselect,poll,epoll,I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select,pselect,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内

Python——IO多路复用之select模块epoll方法

Python——IO多路复用之select模块epoll方法 使用epoll方法实现IO多路复用,使用方法基本与poll方法一致,epoll效率要高于select和poll. .├── epoll_client.py├── epoll_server.py└── settings.py # settings.py HOST = 'localhost' PORT = 5555 buffersize = 1024 ADDR = HOST, PORT # poll_server.py from sett

IO多路复用之select

基本概念 IO多路复用是指内核(线性扫描)一旦发现进程指定的一个或者多个IO条件准备就绪,它就通知该进程,执行定义的操作. 适用场景 1.当客户处理多个描述符时(一般是交互式输入和网络套接字),必须使用I/O复用. 2.当一个客户同时处理多个套接字时,而这种情况是可能的,但很少出现. 3.如果一个TCP服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到I/O复用. 4.如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用. 5.如果一个服务器要处理多个服务或多个协议,一般

IO多路复用之select总结

1.基本概念 IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用. (2)当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现. (3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用. (4)如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用. (5)如果一个服务器要处理多个服务或多个协议,一

python IO多路复用之select

说起IO操作我们最先想到的就是读写文件.其实python中对有三种IO操作,打开文件,使用socket进行网络连接和系统的标准输入输出sys.stdin和sys.stdout.我们先来看一段socket服务端的代码: import socket ip_port = ('127.0.0.1',9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True:     """     程序运行到accept()

IO多路复用:select、poll、epoll示例

一.IO多路复用 所谓IO多路复用,就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux支持IO多路复用的系统调用有select.poll.epoll,这些调用都是内核级别的.但select.poll.epoll本质上都是同步I/O,先是block住等待就绪的socket,再是block住将数据从内核拷贝到用户内存. 当然select.poll.epoll之间也是有区别的,如下表: \ select poll e

聊聊IO多路复用之select、poll、epoll详解

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程.IO多路复用适用如下场合: 当客户处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用. 当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现. 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用. 如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用. 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用. 与多进程和多线程技术相

【select模块】select IO多路复用和select实现FTP

select是全平台通用的IO多路复用模块.最大连接数:1024. poll和epoll没有最大连接数限制,但只能用在linux平台. selectors是再封装模块,推荐使用.下篇会讨论. select.select(rlist, wlist, xlist[, timeout])? This is a straightforward interface to the Unix select() system call. The first three arguments are sequenc

socket + select 完成伪并发操作

1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 import socket 5 #创建一个socket对象 6 sk1 = socket.socket() 7 #绑定ip和端口 8 sk1.bind(('127.0.0.1', 8001)) 9 #监听 10 sk1.listen() 11 #定义一个字典存放客户端发送的信息 12 message_dict = {} 13 #inputs用于存放socket对象 14 inputs =