天天看点

Python实现web聊天室

使用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,如需转载请自行联系原作者