博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
epoll编写web服务器
阅读量:5346 次
发布时间:2019-06-15

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

编写一个简单的web服务器,向每一个连接服务器的网页浏览器返回一行文本。

脚本核心在web服务器的初始化过程中调用select.epoll(),注册服务器的文件描述符,已达到事件通知的目的。

1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3  4 import socket 5 import select 6 import argparse 7  8 SERVER_HOST = 'localhost' 9 10 EOL1 = b'\n\n'11 EOL2 = b'\n\r\n'12 SERVER_RESPONSE = b"""HTTP/1.1 200 OK\r\nDate:Mon, 1 Apr 2013 01:01:01 GMT\r\nContent-Type:text/plain\r\nContent-Length: 25\r\n\r\nHello from Epoll Server!"""13 14 class EpollServer(object):15     """ a socket server using epoll"""16     def __init__(self, host=SERVER_HOST, port=0):17         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)18         #创建套接字19         self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)20         #设置当前套接字选项为可重用21         self.sock.bind((host, port))#绑定22         self.sock.listen(1)#监听23         self.sock.setblocking(0)#设置套接字模式为非阻塞24         self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)25         #socket阻塞模式自动开启Nagle算法。设置套接字选项关闭。Nagle算法用于对缓冲区内的一定数量的消息进行自动连接。26         print "Started Epoll Server"27         self.epoll = select.epoll()#创建epoll对象28         self.epoll.register(self.sock.fileno(), select.EPOLLIN)29            #为该socket的read event注册interest30            #EPOLLIN表示对应的文件描述符可以读,包括对端SOCKET正常关闭31            #fileno()返回的是该socket的一个整型文件描述符32 33     def run(self):34         """Executes epoll server operation"""35         try:36             connections = {}    #连接对象与socket对象的映射37             requests = {}        38             responses = {}39             while True:40                 events = self.epoll.poll(1)41                 #查询epoll对象是否可能发生任何interest的事件。1等待一秒42                 for fileno, event in events:#遍历事件43                     #如果事件发生在服务器44                     if fileno == self.sock.fileno():45                         connection, address = self.sock.accept()#接收客户端socket和地址46                         connection.setblocking(0)#设置非阻塞模式47                         self.epoll.register(connection.fileno(), select.EPOLLIN)48                         #为新的socket的read event注册兴趣                    49                         connections[connection.fileno()] = connection#添加到connections50                         requests[connection.fileno()] = b''51                         responses[connection.fileno()] = SERVER_RESPONSE#要发送的内容52 53                     #如果一个读事件发生在客户端,那么读取从客户端发来的新数据54                     elif event & select.EPOLLIN:55                         requests[fileno] += connections[fileno].recv(1024)56                         if EOL1 in requests[fileno] or EOL2 in requests[fileno]:57                             self.epoll.modify(fileno, select.EPOLLOUT)58                              #注销对read event的interest,注册对write event的interest59                              print('-'*40 + '\n' + requests[fileno].decode()[:-2])60                             #输出完整的请求,去除最后一个\r\n61 62                      #如果一个写事件发生在客户端,那么可能要接受来自客户端的新数据63                     elif event & select.EPOLLOUT:64                     #EPOLLOUT表示对应的文件描述符可以写65                         byteswritten = connections[fileno].send(responses[fileno])66                         responses[fileno] = responses[fileno][byteswritten:]67                         if len(responses[fileno]) == 0:#如果无响应68                             self.epoll.modify(fileno, 0)#禁用interest69                             connections[fileno].shutdown(socket.SHUT_RDWR)70                             #将对应的socket连接关闭71 72                     #如果一个中止事件发生在客户端73                     elif event & select.EPOLLHUP:74                     #EPOLLHUP表示对应的文件描述符被挂断75                         self.epoll.unregister(fileno)#注销客户端interest76                         connections[fileno].close()#关闭socket连接77                         del connections[fileno]#删除映射78         finally:79             self.epoll.unregister(self.sock.fileno())#注销服务器interest80             self.epoll.close()#关闭服务器epoll81             self.sock.close()#关闭服务器socket82 83 if __name__ == '__main__':84     parser = argparse.ArgumentParser(description='Socket Server Example with Epoll')85     parser.add_argument('--port', action="store", dest="port", type=int, required=True)86     given_args = parser.parse_args()87     port = given_args.port88     server = EpollServer(host=SERVER_HOST, port=port)89     server.run()

 

参考文献: 《Python Network Programming Cookbook》

      http://scotdoyle.com/python-epoll-howto.html#source-code

转载于:https://www.cnblogs.com/tindin/p/4650799.html

你可能感兴趣的文章
myeclipse10 与myeclipse2017可以并存
查看>>
C语言 const与指针
查看>>
磁盘文件系统RAW文件怎样恢复
查看>>
第二章 测试环境搭建(下)
查看>>
go语言学习基础-编译文件
查看>>
前端网址搜藏
查看>>
bzoj2456 mode
查看>>
【Python之路Day1】基础篇
查看>>
wordpress stratus模板使用 产品显示问题
查看>>
第一课:网络爬虫准备
查看>>
IE8 input X 去掉文本框的叉叉和密码输入框的眼睛图标
查看>>
C#内联汇编的一个类
查看>>
AFNetworking 显示不支持“Content-Type:text/plain”的解决方法
查看>>
[WPF] 将普通的Library工程,改造成WPF Custom Control 的Library
查看>>
2019春第十一周作业
查看>>
深入浅出SharePoint——无法搜索当前站点的数据
查看>>
js的线程和同步异步以及console.log机制
查看>>
JavaScript 框架比较
查看>>
前端资源大整理
查看>>
CF815D Karen and Cards 官方题解翻译
查看>>