Python-基于socket和select模块实现IO多路复用

‘‘‘IO指的是输入输出,一部分指的是文件操作,还有一部分网络传输操作,例如soekct就是其中之一;多路复用指的是利用一种机制,同时使用多个IO,例如同时监听多个文件句柄(socket对象一旦传送或者接收信息),一旦文件句柄出现变化就会立刻感知到‘‘‘1.下面通过IO多路复用实现多人同时连接socket服务器
import socket

sk1 = socket.socket()#sk1,sk2,sk3这就是一个文件描述符
sk1.bind((‘127.0.0.1‘,8002))
sk1.listen()

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

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

inputs = [sk1,sk2,sk3]
import select
while True:
    ‘‘‘[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
    一旦某个句柄发生变化就会被监听到
    ‘‘‘
    #如果有人链接sk1,则会被添加进列表,r_list = [sk1]
    r_list,w_list,e_list = select.select(inputs,[],[],1)#1表示等一秒,在while执行到这里的时候监测一秒,没有人来链接的话就接着循环
    #print(r_list,sk1.listen())
    for sk in r_list:
        conn,address = sk.accept()
        #print(conn,address)
        conn.sendall(bytes(‘你好‘,encoding=‘utf-8‘))
        conn.close()
#客户端一
import socket

obj = socket.socket()
obj.connect((‘127.0.0.1‘,8002))
content = str(obj.recv(1024),encoding=‘utf-8‘)
print(content)

obj.close()

#客户端二
import socket

obj = socket.socket()
obj.connect((‘127.0.0.1‘,8003))
content = str(obj.recv(1024),encoding=‘utf-8‘)
print(content)

obj.close()

#客户端三
import socket

obj = socket.socket()
obj.connect((‘127.0.0.1‘,8004))
content = str(obj.recv(1024),encoding=‘utf-8‘)
print(content)

obj.close()

执行结果:只要启动服务器端,然后不同的客户端多次启动都能收到信息,多个端口成功被监听

2. 下面使用select模块实现多路复用,使同一个端口同时接收多个链接

import socket

sk1 = socket.socket()#sk1,sk2,sk3这就是一个文件描述符
sk1.bind((‘127.0.0.1‘,8002))
sk1.listen()

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

inputs = [sk1]
import select

#epoll效率更高,但是Windows不支持,它是谁有问题就告诉它,不用循坏
while True:
    ‘‘‘[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
    一旦某个句柄发生变化(某人来链接)就会被监听到
    ‘‘‘
    #如果有人链接sk1,则会被添加进列表,r_list = [sk1]
    r_list,w_list,e_list = select.select(inputs,[],[],1)
    ‘‘‘第三个参数是监听错误的,只要有错误出现,就会被监听到,返回e_list
       第二个参数返回给w_list,只要传了什么,就原封不动的传给w_list‘‘‘
    print(‘正在监听 %s 多少个对象‘ % len(inputs))
    for sk in r_list:
        if sk == sk1:
            #句柄跟服务器端的对象一样,表示有新用户来链接了
            conn,address = sk.accept()
            inputs.append(conn)#加入去之后,inputs有一个链接对象和服务器对象
        else:
            #有老用户发消息了
            try:
                data_byte =sk.recv(1024)

                data_str =str(data_byte,encoding=‘utf-8‘)
                sk.sendall(bytes(data_str+‘收到了‘,encoding=‘utf-8‘))
            except:#空信息表示客户端断开链接,所以要在监听中移除

                inputs.remove(sk)#这里的sk就是之前传进去的conn,因为r_list接收的是有变化的值
                

启动这个服务端之后,就可以实现多路复用了,可以接收多个客户端同时连接

3.下面介绍一些多路操作里面的读写分离

import socket

sk1 = socket.socket()#sk1就是一个文件描述符
sk1.bind((‘127.0.0.1‘,8002))
sk1.listen()
inputs = [sk1]#被检测发生变动的句柄放这里
outputs=[]#用来记录谁给服务端发过信息,以便回复
message_dict = {}#接收信息的,根据句柄形成键值对
import select

#epoll效率更高,但是Windows不支持,它是谁有问题就告诉它,不用循坏
while True:
    ‘‘‘[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
    一旦某个句柄发生变化(某人来链接)就会被监听到
    ‘‘‘
    #如果有人链接sk1,则会被添加进列表,r_list = [sk1]
    r_list,w_list,e_list = select.select(inputs,outputs,inputs,1)
    ‘‘‘第三个参数是监听错误的,只要有错误出现,就会被监听到,返回e_list
       第二个参数返回给w_list,只要传了什么,就原封不动的传给w_list‘‘‘
    print(‘正在监听 %s 多少个对象‘ % len(inputs))
    for sk in r_list:
        if sk == sk1:
            #句柄跟服务器端的对象一样,表示有新用户来链接了
            conn,address = sk.accept()
            inputs.append(conn)#加入去之后,inputs有一个链接对象和服务器对象
            message_dict[conn]=[]#字典的key是具体的链接对象
        else:
            #有老用户发消息了
            try:
                data_byte =sk.recv(1024)

            except Exception as e:#空信息表示客户端断开链接,所以要在监听中移除
                print(e)
                inputs.remove(sk)#这里的sk就是之前传进去的conn,因为r_list接收的是有变化的值
            else:
                data_str = str(data_byte, encoding=‘utf-8‘)

                message_dict[sk].append(data_str)
                outputs.append(sk)#把传送数据的句柄添加进去第二个参数
    for conn in w_list:
        recv_str=message_dict[conn][0]#拿到我们收到了的信息
        del message_dict[conn][0]#删除信息,防止下次出现一样的消息
        print(recv_str)
        conn.sendall(bytes(recv_str+‘收到了‘,encoding=‘utf-8‘))
        outputs.remove(conn)#回复完成之后在列表删除
    for sk_or_conn in e_list:
        e_list.remove(sk_or_conn)

这样可以形成简单的读写分离操作

原文地址:https://www.cnblogs.com/benchdog/p/9350164.html

时间: 2024-10-05 05:50:12

Python-基于socket和select模块实现IO多路复用的相关文章

Python 中 socket 和 socketserver模块

Client/Server Architecture (CS架构) 说socket之前先说一点cs架构的问题.什么是CS架构? 不同的人对于这个问题有不同的回答以及你说的是硬件还是软件,但是无论哪一种情况都离不开一个前提假设:服务端是为一台或多台客服端提提供服务的硬件和软件的结合体.它存在的仅有的目的就是等待客服端的请求,对客服端提供反应,之后等待更多的请求. 客服端(client)为特殊的请求链接服务器,发送必要的数据,等待服务器回复,要么完成请求要么失败.服务端无限制的运行,不断的处理请求:

python基础篇【第十篇】多路复用、多线程

一.小知识点(作用域) 进入主题之前先分享一个有关某公司一道python自动化的面试题: 首先说一下作用域的关系,如以下案例: if 1==1: name="tom" print(name) 看以上代码你觉得会打印出来"tom"吗? 答案是:会的. 这个地方需要了解的是,在Java.c#是有块级作用域的,不会打印出来.在python中无块级作用域可以会被执行 既然已经了解python中无块级作用域,就要了解变量执行的优先级,先从自己本身作用域找,找不到往上一级找,以

10-线程,进程,协程,IO多路复用

- 线程进程介绍 1. 工作最小单元是线程 2. 应用程序 -> 至少有一个进程 -> 至少有一个线程 3. 应用场景: IO密集型:线程 计算密集型:进程 4. GIL,全局解释器锁. - 保证同一个进程中只有一个线程同时被调度- 线程 1. 基本使用 def task(arg): time.sleep(arg) print(arg) for i in range(5): t = threading.Thread(target=task,args=[i,]) # t.setDaemon(Tr

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()

python(十)下:事件驱动与 阻塞IO、非阻塞IO、IO多路复用、异步IO

上节的问题: 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么确定IO操作完了? 一.事件驱动模型介绍 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求: (2)每收到一个请求,创建一个新的线程,来处理该请求: (3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求 第三种就是协程.时间驱动的方式,一般普遍认为第(3)种方式是大多数网络服务器采用的方式 论事件驱动模型 在UI编程中,,常常要对鼠标点击进行相应,

Python全栈开发-Day10-进程/协程/异步IO/IO多路复用

本节内容 多进程multiprocessing 进程间的通讯 协程 论事件驱动与异步IO Select\Poll\Epoll--IO多路复用   1.多进程multiprocessing Python的线程用的是操作系统的原生线程,同样python的进程用的是操作系统的原生进程. 多进程之间没有锁的概念,多进程之间数据不能互相访问,所以不存在互斥锁.GIL问题又是仅仅出现在多线程中. 所以如果我们启动8个进程,每个进程有一个主线程,即8个线程,分别运行在8个CPU上,就可以充分利用多核的优势了.

python IO 多路复用

一.epoll epoll 参考链接: https://www.cnblogs.com/Alanpy/articles/5125986.html epoll  参考链接: https://www.cnblogs.com/maociping/p/5132583.html 二. selectors 模块 实现IO多路复用 selectors 参考链接: https://blog.csdn.net/jjjndk1314/article/details/79682958 三.select 模块 样例:

小贞贞python关于requests和tkinter模块项目实战

requests模块主要是用于网页的请求,获取相应数据 tkinter模块是python基于GUI的一个模块,大致模块如下: 具体可参照:https://www.cnblogs.com/shwee/p/9427975.html 今天给大家介绍,自制翻译小工具的具体项目实战: 整体是实现方式: 步骤一:通过requets模块请求百度翻译 步骤二:通过tkinter模块制作界面,将界面输入的内容传入requests模块,然后点击“翻译”按钮,显示requests模块返回的数据 步骤三:制作成一个ex

5Python全栈之路系列之IO多路复用

Python全栈之路系列之IO多路复用 What is IO Multiplexing? IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程. 举例说明 你是一名老师(线程),上课了(启动线程),这节课是自习课,学生都在自习,你也在教室里面坐着,只看着这帮学生,什么也不干(休眠状态),课程进行到一半时,A同学(socket)突然拉肚子,举手说:老湿我要上厕所(read),然后你就让他去了,过了一会,B同学(socket)在自习的过程中有个问题不太懂,就请你过去帮她