博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 关于epoll的学习
阅读量:6157 次
发布时间:2019-06-21

本文共 2832 字,大约阅读时间需要 9 分钟。

      在linux中,默认情况下所有的socket都是blocking;当 用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据。对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),这个时候kernel就要等待足够的数据到来。而在用户进程这边,整 个进程会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除 block的状态,重新运行起来。

    所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。

    几乎所有的程序员第一次接触到的网络编程都是从listen()、send()、recv() 等接口开始的,这些接口都是阻塞型的。使用这些接口可以很方便的构建服务器/客户机的模型。

    在python socket模型当中,当使用socket初次编程的时候都会遇到一个阻塞问题;当一个socet的server被一个client暂用之后;参数了阻塞,新的连接是不能进来的,当然还有一个封装的socketserver利用多线程很好的解决了这个问题;但是我们思考一个问题,就是当连接数很多时候很多的线程是否对我们系统照成影响呢,当然可以通过线程池来解决这个问题,但是瓶颈也会产生。

    下面学习用epoll的方式来进行网络编程,当然对比与select只能打开1024(可以调整,但是文件描述符多了性能会下降)epoll的优势就非常明显了。

   代码:

#!/usr/bin/env python# -*- coding: utf-8 -*-import socket, selectimport Queue,os serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)server_address = ("", 8999)serversocket.bind(server_address)serversocket.listen(1)print  "服务器启动成功,监听IP:" , server_addressserversocket.setblocking(0)   #设置成非阻塞时间timeout = 10#新建epoll事件对象,后续要监控的事件添加到其中epoll = select.epoll()#注册服务器监听fd到等待读事件集合epoll.register(serversocket.fileno(), select.EPOLLIN)message_queues = {} fd_to_socket = {serversocket.fileno():serversocket,}while True:#  print "等待活动连接......"  #轮询注册的事件集合  events = epoll.poll(timeout)#  if not events:#     print "epoll超时无活动连接,重新轮询......"#     continue#  print "有" , len(events), "个新事件,开始处理......"  for fd, event in events:     socket = fd_to_socket[fd]     #可读事件     if event & select.EPOLLIN:         #如果活动socket为服务器所监听,有新连接         if socket == serversocket:            connection, address = serversocket.accept()            print "新连接:" , address            connection.setblocking(0)            #注册新连接fd到待读事件集合            epoll.register(connection.fileno(), select.EPOLLIN)            fd_to_socket[connection.fileno()] = connection            message_queues[connection]  = Queue.Queue()         #否则为客户端发送的数据         else:            data = socket.recv(1024)            if data:               print "收到数据:" , data , "客户端:" , socket.getpeername()               message_queues[socket].put(data)               #修改读取到消息的连接到等待写事件集合               epoll.modify(fd, select.EPOLLOUT)     #可写事件     elif event & select.EPOLLOUT:        try:           msg = message_queues[socket].get_nowait()           xiaoluo = os.popen(msg).read()        except Queue.Empty:           print socket.getpeername() , " queue empty"           epoll.modify(fd, select.EPOLLIN)        else :           print "发送数据:" , data , "客户端:" , socket.getpeername()           socket.send(xiaoluo)     #关闭事件     elif event & select.EPOLLHUP:        epoll.unregister(fd)        fd_to_socket[fd].close()        del fd_to_socket[fd]epoll.unregister(serversocket.fileno())epoll.close()serversocket.close()

这样就实现了无阻塞的io SOcket模型:

可以参考老外写的文章:

转载地址:http://zuifa.baihongyu.com/

你可能感兴趣的文章
spring+jotm+ibatis+mysql实现JTA分布式事务
查看>>
MyBatis启动:MapperStatement创建
查看>>
调查问卷相关
查看>>
eclipse启动无响应,老是加载不了revert resources,或停留在Loading workbench状态
查看>>
1. Git-2.12.0-64-bit .exe下载
查看>>
怎样关闭“粘滞键”?
查看>>
[转]React 教程
查看>>
拓扑排序介绍
查看>>
eclipse打开工作空间(workspace)没有任务反应
查看>>
使用Sybmol模块来构建神经网络
查看>>
字符串去分割符号
查看>>
WPF中,多key值绑定问题,一个key绑定一个界面上的对象
查看>>
UML类图简明教程
查看>>
java反编译工具(Java Decompiler)
查看>>
Android开发之自定义对话框
查看>>
微信Access Token 缓存方法
查看>>
Eclipsed的SVN插件不能识别之前工作空间的项目
查看>>
Linux 查看iptables状态-重启
查看>>
amazeui学习笔记一(开始使用2)--布局示例layouts
查看>>
c#中lock的使用(用于预约超出限额的流程)
查看>>