码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2018-07-22 17:12:36      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:启动服务   soc   obj   支持   enc   之一   close   返回   用户   

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

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

 

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

标签:启动服务   soc   obj   支持   enc   之一   close   返回   用户   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!