在Python中如何使用Linux的epoll

目录

  1. 序言
  2. 阻塞socket编程示例
  3. 异步socket的好处以及Linux epoll
  4. 带epoll的异步socket编程示例
  5. 性能注意事项
  6. 源代码

 

序言

从2.6开始,Python包含了访问Linux epoll库的API。这篇文章用几个简单的python 3例子来展示下这个API。欢迎大家质疑和反馈

阻塞socket编程示例

示例1用python3.0搭建了一个简单的服务:在8080端口监听HTTP请求,把它打印到控制台,并返回一个HTTP响应消息给客户端。

  1. 第9行:创建服务器socket。
  2. 第10行:允许在11行使用bind()来监听指定端口,即使这个端口最近被其他程序监听。没有这个设置的话,服务不能运行,直到一两分钟后,这个端口不再被之前的程序使用。
  3. 第11行:监听这台机器所有可用的IPv4地址上面的8080端口。
  4. 第12行:通知服务端socket开始接受来自客户端的连接。
  5. 第 14行:这行代码直到接收到一个客户端连接才会完成。这时,服务端socket会在服务端机器上面创建一个新的socket,用来和客户端通信。这个新的 socket在代码里面就是accept()调用返回的clientconnection 对象。返回的address对象代表着客户端的IP和端口。
  6. 第15-17行:组装从客户端传输过来的数据,直到HTTP请求完成。HTTP协议可以参考这里
  7. 第18行:把请求打印到控制台,验证操作是否正确。
  8. 第19行:发送响应回客户端。
  9. 第20-22行:关闭和客户端的连接以及服务端监听socket。

官方howto中对python socket编程有更详细的描述。

Example 1 (All examples use Python 3)

1  import socket
2
3  EOL1 = b'\n\n'
4  EOL2 = b'\n\r\n'
5  response  = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
6  response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
7  response += b'Hello, world!'
8
9  serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10  serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
11  serversocket.bind(('0.0.0.0', 8080))
12  serversocket.listen(1)
13
14  connectiontoclient, address = serversocket.accept()
15  request = b''
16  while EOL1 not in request and EOL2 not in request:
17     request += connectiontoclient.recv(1024)
18  print(request.decode())
19  connectiontoclient.send(response)
20  connectiontoclient.close()
21
22  serversocket.close()
View Code

 

 

示例2在15行增加了一个循环来不断的处理来自客户端的连接,直到用户中断(比如键盘中断)。这个例子更清楚的说明服务端socket从不和客户端交换数据。相反的,它接收客户端的连接,然后在这台服务器上面创建一个新的socket用来和客户端通信。

在23-24行的finally语句,可以确保服务端负责监听的socket会关闭,即使有异常发生。

Example 2

1  import socket
2
3  EOL1 = b'\n\n'
4  EOL2 = b'\n\r\n'
5  response  = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
6  response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
7  response += b'Hello, world!'
8
9  serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10  serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
11  serversocket.bind(('0.0.0.0', 8080))
12  serversocket.listen(1)
13
14  try:
15     while True:
16        connectiontoclient, address = serversocket.accept()
17        request = b''
18        while EOL1 not in request and EOL2 not in request:
19            request += connectiontoclient.recv(1024)
20        print('-'*40 + '\n' + request.decode()[:-2])
21        connectiontoclient.send(response)
22        connectiontoclient.close()
23  finally:
24     serversocket.close()
View Code

相关文章: