Python实现web聊天室「建议收藏」

Python实现web聊天室「建议收藏」使用Python模块中的select模块实现web聊天室功能select模块Python中的select模块专注于I/O多路复用,提供了selectpollepoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)参数:可接受四个参数(前三个必须)r…

大家好,又见面了,我是你们的朋友全栈君。

使用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 

in 
rlist:
                
if 

=
= 
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 

in 
self
.socketList:
            
if 
i !
= 

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
    

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



本文转自 粗粮面包 51CTO博客,原文链接:http://blog.51cto.com/culiangmianbao/2058054,如需转载请自行联系原作者

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152175.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月22日 上午7:16
下一篇 2022年6月22日 上午7:36


相关推荐

  • 【SpringBoot】4、SpringBoot中整合Freemarker模板引擎

    【SpringBoot】4、SpringBoot中整合Freemarker模板引擎FreeMarker 是一款模板引擎 即一种基于模板和要改变的数据 并用来生成输出文本 HTML 网页 电子邮件 配置文件 源代码等 的通用工具 它不是面向最终用户的 而是一个 Java 类库 是一款程序员可以嵌入他们所开发产品的组件 FreeMarker 是一个很值得去学习的模版引擎 它是基于模板文件生成其他文本的通用工具 本文主要介绍在 SpringBoot 中如何整合 FreeM

    2026年3月20日
    3
  • MySQL/Oracle数据库优化总结(非常全面)「建议收藏」

    MySQL/Oracle数据库优化总结(非常全面)

    2022年4月6日
    174
  • 页面可见性改变事件:visibilitychange

    页面可见性改变事件:visibilitychange1、PC浏览器上(以谷歌浏览器为例)刷新H5页面,会触发该事件,由于刷新导致该页面消失时,会检测到document.visibilityState===‘hidden’切换页面(包括切换离开和切换回来),导致页面暂时不处于激活状态时,会触发该事件。切换离开时document.visibilityState===‘hidden’,切换回该页面时,document.visibilityS…

    2022年6月18日
    45
  • 负数补码的移位规则

    负数补码的移位规则由原码求得补码的方法 1 定义法补码解决了计算机在进行数值运算的两个问题 一个是减法运算能不能使用加法电路 另一个是原码中 0 的表示不唯一 正数的补码就是其原码 整数负数的补码是 真值 以 2 为底以数值位数加一为指数的幂 模 即以这个幂为模的补数 这里描述下补码的几何意义 大家可以画一个数轴 假定数值位有三位 模是 16 那么加上一位符号位 数轴从 0 000 开始往右依次加一是 0 001 0 010 0 011 0 111 共八个数 这个时候如果继续

    2026年3月17日
    4
  • linux ubuntu安装_vscode electron

    linux ubuntu安装_vscode electron环境:ubuntux86_64apache2.4mysql5.7php7.0方法一:这个方法是我安装成功的方法,所以写在第一个.步骤:1.在官网https://code.visualstudio.com/Download下载相应的deb包到自己电脑上我下载的是64bit的.2.打开相应目录的终端,执行命令sudodpkg-icode_1.2…

    2026年1月15日
    7
  • OpenClaw 定时任务配置详解

    OpenClaw 定时任务配置详解

    2026年3月14日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号