使用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拷貝到核心空間(每次都要拷貝),導緻效率下降
監聽的的實作是通過周遊所有的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
<code>#/usr/bin/env python</code>
<code>#-*- coding:utf-8 -*-</code>
<code>import</code> <code>socket</code>
<code>import</code> <code>select</code>
<code># 封裝</code>
<code>class</code> <code>SelectServer(</code><code>object</code><code>):</code>
<code> </code><code># 定義主函數</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, host, port, backlog):</code>
<code> </code><code>self</code><code>.host </code><code>=</code> <code>host</code>
<code> </code><code>self</code><code>.port </code><code>=</code> <code>port</code>
<code> </code><code>self</code><code>.address </code><code>=</code> <code>(host, port)</code>
<code> </code><code>self</code><code>.backlog </code><code>=</code> <code>backlog</code>
<code> </code><code>self</code><code>.server </code><code>=</code> <code>None</code>
<code> </code><code>self</code><code>.socketList </code><code>=</code> <code>list</code><code>()</code>
<code> </code><code>def</code> <code>_initSocket(</code><code>self</code><code>):</code>
<code> </code><code>self</code><code>.server </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>
<code> </code><code>self</code><code>.server.bind(</code><code>self</code><code>.address)</code>
<code> </code><code>self</code><code>.server.listen(</code><code>self</code><code>.backlog)</code>
<code> </code><code>self</code><code>.socketList.append(</code><code>self</code><code>.server)</code>
<code> </code><code>print</code><code>(</code><code>"chat room has start!"</code><code>)</code>
<code> </code><code>while</code> <code>1</code><code>:</code>
<code> </code><code>rlist, wlist, elist </code><code>=</code> <code>select.select(</code><code>self</code><code>.socketList, [], [])</code>
<code> </code><code>for</code> <code>r </code><code>in</code> <code>rlist:</code>
<code> </code><code>if</code> <code>r </code><code>=</code><code>=</code> <code>self</code><code>.server:</code>
<code> </code><code>serverConn, clienAddr </code><code>=</code> <code>self</code><code>.server.accept()</code>
<code> </code><code>self</code><code>.socketList.append(serverConn)</code>
<code> </code><code>print</code><code>(</code><code>"{0}進入了房間"</code><code>.</code><code>format</code><code>(clienAddr))</code>
<code> </code><code>self</code><code>.broadcast(r, </code><code>"{0}進入了房間"</code><code>.</code><code>format</code><code>(clienAddr))</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>data </code><code>=</code> <code>r.recv(</code><code>2048</code><code>)</code>
<code> </code><code>if</code> <code>data:</code>
<code> </code><code>print</code><code>(</code><code>"{0}: {1}"</code><code>.</code><code>format</code><code>(clienAddr, data))</code>
<code> </code><code>self</code><code>.broadcast(r, </code><code>"{0}: {1}"</code><code>.</code><code>format</code><code>(clienAddr, data))</code>
<code> </code><code>except</code> <code>Exception as e:</code>
<code> </code><code>self</code><code>.broadcast(r, </code><code>"{0}下線"</code><code>.</code><code>format</code><code>(clienAddr))</code>
<code> </code><code>print</code><code>(</code><code>"{0}下線"</code><code>.</code><code>format</code><code>(clienAddr))</code>
<code> </code><code>r.close()</code>
<code> </code><code>self</code><code>.socketList.remove(r)</code>
<code> </code><code>self</code><code>.server.close()</code>
<code> </code><code># 定義廣播函數</code>
<code> </code><code>def</code> <code>broadcast(</code><code>self</code><code>, r, data):</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>self</code><code>.socketList:</code>
<code> </code><code>if</code> <code>i !</code><code>=</code> <code>r </code><code>and</code> <code>i !</code><code>=</code> <code>self</code><code>.server:</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>i.sendall(data)</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>i.close()</code>
<code> </code><code>self</code><code>.socketList.remove(i)</code>
<code># 定義main函數</code>
<code>def</code> <code>main():</code>
<code> </code><code>selectServer </code><code>=</code> <code>SelectServer(host</code><code>=</code><code>"192.168.154.131"</code><code>, port</code><code>=</code><code>9999</code><code>, backlog</code><code>=</code><code>5</code><code>)</code>
<code> </code><code>selectServer._initSocket()</code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>:</code>
<code> </code><code>main()</code>
client端代碼
<code>import</code> <code>socket, select, string, sys</code>
<code>import</code> <code>time</code>
<code># main function</code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>"__main__"</code><code>:</code>
<code> </code><code>host </code><code>=</code> <code>"192.168.154.131"</code>
<code> </code><code>port </code><code>=</code> <code>9999</code>
<code> </code><code>s </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>
<code> </code><code>s.settimeout(</code><code>2</code><code>)</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>s.connect((host, port))</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'Unable to connect'</code><code>)</code>
<code> </code><code>sys.exit()</code>
<code> </code><code>print</code><code>(</code><code>'Connected to remote host. Start sending messages'</code><code>)</code>
<code> </code><code>while</code> <code>1</code><code>:</code>
<code> </code><code>rlist </code><code>=</code> <code>[sys.stdin, s]</code>
<code> </code><code>read_list, write_list, error_list </code><code>=</code> <code>select.select(rlist, [], [])</code>
<code> </code><code>for</code> <code>sock </code><code>in</code> <code>read_list:</code>
<code> </code><code>if</code> <code>sock </code><code>=</code><code>=</code> <code>s:</code>
<code> </code><code>data </code><code>=</code> <code>sock.recv(</code><code>2048</code><code>)</code>
<code> </code><code>if</code> <code>not</code> <code>data:</code>
<code> </code><code>continue</code>
<code> </code><code>sys.stdout.write(data)</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>msg </code><code>=</code> <code>raw_input</code><code>(</code><code>"我說: "</code><code>)</code>
<code> </code><code>s.sendall(msg)</code>
<code></code>
本文轉自 粗糧面包 51CTO部落格,原文連結:http://blog.51cto.com/culiangmianbao/2058054,如需轉載請自行聯系原作者