原文地址: http://scotdoyle.com/python-epoll-howto.html

文章里面的代码可以 点击这里下载.

介绍

从2.6版本开始, python 提供了使用linux epoll 的功能. 这篇文章通过3个例子来大致介绍如何使用它. 欢迎提问和反馈.

阻塞式socket通讯

<p>
  第一个例子是一个简单的python3.0版本的服务器代码, 监听8080端口的http请求, 打印结果到命令行, 回应http response给客户端.
</p>

<ul>
  <li>
    行 9: 建立服务器的socket
  </li>
  <li>
    行 10: 允许11行的bind()操作, 即使其他程序也在监听同样的端口. 不然的话, 这个程序只能在其他程序停止使用这个端口之后的1到2分钟后才能执行.
  </li>
  <li>
    行 11: 绑定socket到这台机器上所有IPv4地址上的8080端口.
  </li>
  <li>
    行 12: 告诉服务器开始响应从客户端过来的连接请求.
  </li>
  <li>
    行 14: 程序会一直停在这里, 直到建立了一个连接. 这个时候, 服务器socket会建立一个新的socket, 用来和客户端通讯. 这个新的socket是accept()的返回值, address对象标示了客户端的IP地址和端口.
  </li>
  <li>
    行 15-17: 接收数据, 直到一个完整的http请求被接收完毕. <a href="http://www.jmarshall.com/easy/http/">这是一个简单的http服务器实现</a>.
  </li>
  <li>
    行 18: 为了方便验证, 打印客户端过来的请求到命令行.
  </li>
  <li>
    行 19: 发送回应.
  </li>
  <li>
    行 20-22: 关闭连接, 以及服务器的监听socket.
  </li>
</ul>

<p>

<p>
  <a href="http://docs.python.org/3.0/howto/sockets.html">python官方 HOWTO</a> 里面有具体如何使用socket编程的描述.
</p>

<div>
  <pre class="brush: python; title: Example; notranslate" title="Example">

import socket

EOL1 = b’nn' EOL2 = b’nrn' response = b’HTTP/1.0 200 OKrnDate: Mon, 1 Jan 1996 01:01:01 GMTrn' response += b’Content-Type: text/plainrnContent-Length: 13rnrn' response += b’Hello, world!'

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serversocket.bind((‘0.0.0.0’, 8080)) serversocket.listen(1)

connectiontoclient, address = serversocket.accept() request = b’’ while EOL1 not in request and EOL2 not in request: request += connectiontoclient.recv(1024) print(request.decode()) connectiontoclient.send(response) connectiontoclient.close()

serversocket.close()

<p>
  第2个例子, 我们在15行加上了一个循环, 用来循环处理客户端请求, 直到我们中断这个过程(在命令行下面输入键盘中断, 比如Ctrl-C). 这个例子更明显地表示出来了, 服务器socket并没有用来做数据处理, 而是接受服务器过来的连接, 然后建立一个新的socket, 用来和客户端通讯.
</p>

<p>
  最后的23-24行确保服务器的监听socket最后总是close掉, 即使出现了异常.
</p>

<div>
  <pre class="brush: python; title: Example; notranslate" title="Example">

import socket

EOL1 = b’nn' EOL2 = b’nrn' response = b’HTTP/1.0 200 OKrnDate: Mon, 1 Jan 1996 01:01:01 GMTrn' response += b’Content-Type: text/plainrnContent-Length: 13rnrn' response += b’Hello, world!'

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serversocket.bind((‘0.0.0.0’, 8080)) serversocket.listen(1)

try: while True: connectiontoclient, address = serversocket.accept() request = b’’ while EOL1 not in request and EOL2 not in request: request += connectiontoclient.recv(1024) print(’-’*40 + ’n’ + request.decode()[:-2]) connectiontoclient.send(response) connectiontoclient.close() finally: serversocket.close()