python socket select 一对多_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)

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

对于select里面的参数关系,这里有个武sir画的图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值