欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python并发原理(阻塞、非阻塞、epoll)

程序员文章站 2023-08-26 13:54:19
在Linux系统中 01 阻塞服务端 02 非阻塞服务端 03 epoll服务端 04 客户端 ......

在Linux系统中

01 阻塞服务端

特征:1对1,阻塞。

 

 1 import socket
 2 
 3 server = socket.socket()        #生成套接字对象
 4 server.bind(('0.0.0.0', 8000))    #套接字绑定ip和端口,变为监听套接字
 5 server.listen(5)                    #开始监听
 6 
 7 while True:
 8     conn, addr = server.accept()        #建立连接,生成对等套接字
 9     print('用户连接:', addr)
10     while True:
11         try:
12             data = conn.recv(1024)
13             if data == b'Q' or data == b'q':
14                 print('用户退出:', addr)
15                 break
16             else:
17                 print('收到的消息:', data.decode())
18                 conn.send(data)
19         except Exception as e:
20             print(e)
21             conn.close()
22             break

 


 

 

02 非阻塞服务端

特征:1对多,非阻塞,占用资源多。

 

 1 import socket
 2 
 3 server = socket.socket()        #创建套接字
 4 server.setblocking(False)       #把套接字设置为非阻塞
 5 server.bind(('0.0.0.0', 8001))  #绑定IP和端口
 6 server.listen(5)                #监听端口
 7 
 8 
 9 all_connection = []             #保存已经连接的客户
10 while True:
11     #只管连接的事情
12     try:
13         conn, addr = server.accept()    # 建立连接,没有就抛出异常
14         conn.setblocking(False)         #设置非阻塞
15         print('用户连接:', addr)
16         all_connection.append(conn)
17     except Exception as e:
18         pass
19 
20 
21     #处理已经连接用户的消息
22     handle = all_connection.copy()  #完全拷贝了列表
23     for connection in handle:
24         try:
25             recv_data = connection.recv(1024)
26             if recv_data:
27                 print(recv_data.decode())
28                 connection.send(recv_data)
29             else:                               #客户端消息处理完了,已经断开了连接
30                 print('断开连接', connection)
31                 connection.close()
32                 all_connection.remove(connection)       #从客户列表里移除断开连接的客户
33         except Exception as e:
34             pass

 


 

 

03 epoll服务端

特征:1对多,非阻塞,占用资源少;
epoll:注册惰性事件回调。

 

 1 import selectors #调用epoll的模块
 2 import socket
 3 
 4 epoll = selectors.EpollSelector()   #生成一个epoll
 5 server = socket.socket()            #生成套接字
 6 server.bind(('', 8082))  #参数1‘’与‘0.0.0.0’等价,表示ip都可接入
 7 server.listen(100)
 8 
 9 
10 #回调函数
11 def create_conneciton(server):
12     #百分百有人连接,不会阻塞
13     conn, addres = server.accept()  #生成对等连接套接字
14 
15 
16     #处理消息的函数注册
17     epoll.register(conn, selectors.EVENT_READ, read_data)
18     return conn
19 
20 
21 
22 #回调函数   处理消息
23 def read_data(conn):
24 
25     data = conn.recv(1024)
26     if data:
27         print(data)
28         conn.send(data)
29     else:
30         epoll.unregister(conn)  #删掉注册事件
31 
32 
33 #1
34 #把监听套接字和生成对等套接字的函数注册到read事件(有用户连接)
35 epoll.register(server, selectors.EVENT_READ, create_conneciton)
36 
37 
38 #2
39 while True:      #事件循环
40     events = epoll.select()  #去操作系统查询
41 
42     for key,mask in events:
43         sock = key.fileobj      #连接客户端的套接字
44         callback = key.data     #回调函数
45 
46         #read_data(conn),   create_conneciton(server)
47         callback(sock)      #调用函数

 


 

04 客户端

测试服务端。

 

 1 import socket
 2 
 3 client = socket.socket()
 4 client.connect(('127.0.0.1', 8082))
 5 
 6 while True:
 7     data = input('输入数据:')
 8     client.send(data.encode())
 9     recv_data = client.recv(1024)
10     print(recv_data.decode())