python並發(阻塞、非阻塞、epoll)


在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())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM