大家好,又见面了,我是你们的朋友全栈君。
使用Python模块中的select模块实现web聊天室功能
select模块
Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)
参数: 可接受四个参数(前三个必须)
rlist: wait until ready for reading
wlist: wait until ready for writing
xlist: wait for an “exceptional condition”
timeout: 超时时间
select方法:
每次调用slect都要将所有的fd拷贝到内核空间(每次都要拷贝),导致效率下降
每次调用slect都要将所有的fd拷贝到内核空间(每次都要拷贝),导致效率下降
监听的的实现是通过遍历所有的fd,(遍历消耗的时间消耗多)判断是否有数据访问
最大连接数(input中放的文件描述符数量1024)
pull方法:
最大连接数没有限制了,除此之外和select一样。使用较少
epull方法:
内部通过3个函数实现(select是其中一个)
第一个函数:
创建epoll句柄,把所有的fd拷贝到内核空间,只需要拷贝一次
第二个函数: 回调函数
某一个函数或者动作成功完成后,会自动触发一个函数为所有的fd绑定一个回调函数,一旦有数据访问,触发改回调函数,回调函数把fd放到链表中。(只要有活动,把fd放到链表中,动态监听)这样就提高了效率。例子:交试卷
第三个函数,判断链表是否为空
server端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
#/usr/bin/env python #-*- coding:utf-8 -*- import socket import select # 封装 class SelectServer( object ): # 定义主函数 def __init__( self , host, port, backlog): self .host = host self .port = port self .address = (host, port) self .backlog = backlog self .server = None self .socketList = list () def _initSocket( self ): self .server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self .server.bind( self .address) self .server.listen( self .backlog) self .socketList.append( self .server) print ( "chat room has start!" ) while 1 : rlist, wlist, elist = select.select( self .socketList, [], []) for r in rlist: if r = = self .server: serverConn, clienAddr = self .server.accept() self .socketList.append(serverConn) print ( "{0}进入了房间" . format (clienAddr)) self .broadcast(r, "{0}进入了房间" . format (clienAddr)) else : try : data = r.recv( 2048 ) if data: print ( "{0}: {1}" . format (clienAddr, data)) self .broadcast(r, "{0}: {1}" . format (clienAddr, data)) except Exception as e: self .broadcast(r, "{0}下线" . format (clienAddr)) print ( "{0}下线" . format (clienAddr)) r.close() self .socketList.remove(r) self .server.close() # 定义广播函数 def broadcast( self , r, data): for i in self .socketList: if i ! = r and i ! = self .server: try : i.sendall(data) except : i.close() self .socketList.remove(i) # 定义main函数 def main(): selectServer = SelectServer(host = "192.168.154.131" , port = 9999 , backlog = 5 ) selectServer._initSocket() if __name__ = = '__main__' : main() |
client端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#/usr/bin/env python #-*- coding:utf-8 -*- import socket, select, string, sys import time # main function if __name__ = = "__main__" : host = "192.168.154.131" port = 9999 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout( 2 ) try : s.connect((host, port)) except : print ( 'Unable to connect' ) sys.exit() print ( 'Connected to remote host. Start sending messages' ) while 1 : rlist = [sys.stdin, s] read_list, write_list, error_list = select.select(rlist, [], []) for sock in read_list: if sock = = s: data = sock.recv( 2048 ) if not data: continue else : sys.stdout.write(data) else : msg = raw_input ( "我说: " ) s.sendall(msg)
|
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152175.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...