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

介绍

Python已于2.6版本添加访问Linux epoll库的API。这篇教程使用Python 3简要介绍如何使用Linux epoll。

阻塞Socket

例1是一个Pyhton服务端程序,它监听8080端口,接收HTTP请求并将其打印到console,然后对HTTP请求进行回复。

#Example 1
import socket EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
response += b'Hello, world!'
#创建socket
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()

下面的代码添加了一个循环,不断接收客户端的请求直到被我们手动关闭。例2更清楚地展示了服务端创建的socket不直接与客户端进行数据交换,而是服务端socket接收到来自客户端的连接后,创建一个新的socket与该客户端进行通信。

#Example 2
import socket EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
response = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n\r\n'
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() #确保程序即使出现exception,socket也会被关闭
finally:
serversocket.close()

非阻塞Socket和Linux epoll的好处

上面两个例子展示的都是阻塞socket。Python代码执行到某行会停在那里直到某一事件发生。如16行的accept()会被阻塞直到有一个客户端请求连接。19行的recv()会被阻塞直到客户端发送了数据(或没有数据可读取)。21行的send()会被阻塞直到所有要发送给客户端的数据已经Linux被放入了传输队列。

当一个服务端程序使用阻塞socket时,对于每一个客户端,其经常使用一个线程甚至一个专门的进程进行通讯。服务端程序的主线程则主要包括监听的被用来接受客户端请求的socket。其每次接收一个来自客户端的请求,并把新创建的用于和客户端通信的socket传给另外一个线程与客户端进行交互。因为每个线程只与一个客户端进行通讯,某一个线程出现阻塞不会影响到其他线程执行的任务。

使用多线程和阻塞socket进行网络编程写出的代码更加直观、简单,但是有不少缺点。多线程需要考虑到操作系统关于资源共享的常见问题,并且这种编程方式对单核CPU很不友好。

The C10K Problem讨论了若干种处理并发连接的方法,比如使用异步socket。

最新文章

  1. C# 洗牌算法
  2. Android Context 是什么?
  3. hdu 2090
  4. SequoiaDB版本升级及导入导出工具说明
  5. 【转】Maven实战(四)---多模块项目---JBOSS部署问题
  6. POJ 3928 Ping pong
  7. C/C++流程图生成器 C转流程图【worldsing笔记】
  8. 类 BufferedReader
  9. HDU 1512 Monkey King(左偏树+并查集)
  10. 【转】VC6.0打开或者添加工程文件崩溃的解决方法
  11. layer弹出层传值到父页面
  12. ActiveMQ 入门helloworld
  13. 用SDL库播放yuy2 Packed mode
  14. 记一次较坑的eclipse安装AmaterasUML插件经历
  15. 函数式编程之-F#类型系统
  16. 基本数据类型补充,深浅copy
  17. Web的几种上传方式总结
  18. Android各国语言对照表(values-xxx)
  19. java ant 编译打包build.xml完整配置范例
  20. 20155217《网络对抗》Exp04 恶意代码分析

热门文章

  1. 对http的研究
  2. sts创建maven项目 引入spring,报错
  3. ps磨皮的方法
  4. 学习日记14、EF 时间段查询
  5. Java-package import关键字
  6. 1208D Restore Permutation
  7. 纯文本编辑语言markdown
  8. yum安装Development Tools报错问题
  9. day04—JavaScript之面向对象
  10. redis 集群新增节点,slots槽分配,删除节点, [ERR] Calling MIGRATE ERR Syntax error, try CLIENT (LIST | KILL | GET...