python之epoll服务器源码分析
#!/usr/bin/env python
# -*- coding: utf8 -*- import socket, select EOL1 = b'/r/n'
EOL2 = b'/r/n/r/n' # 拼接成的response
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, )
serversocket.bind(('0.0.0.0', )) # 绑定
serversocket.listen() # 监听
serversocket.setblocking() # 设置时非阻塞
print(serversocket.fileno())
epoll = select.epoll() # 准备设计一个IO多路复用
epoll.register(serversocket.fileno(), select.EPOLLIN) # 把上面的serversocket的fileno() 和 监听准备读信号 注册到epoll中去 try:
# 设置三个空字典
connections = {}
requests = {}
responses = {}
while True:
# 查看epoll是否有信号有的话,就放在events中
events = epoll.poll() # 循环events,分别拿到 文件描述号 和对应的事件
for fileno, event in events:
# 如果当前的文件描述号是serversocket,那么说明有新的连接
if fileno == serversocket.fileno():
# 所以就得接受,创建了 连接,拿到了对方的IP地址
connection, address = serversocket.accept()
# connection就是客户端连接过来建立的socket,设置为非阻塞
connection.setblocking()
# 客户端建立的socket也注册到select模块的IO多路复用中去
epoll.register(connection.fileno(), select.EPOLLIN) # 以Connection的文件描述号 作为键 socket作为值保存在connections中
connections[connection.fileno()] = connection # 同时在requests和responses字典中,
# requests中 以connection.fileno() 作为键 以请求的内容作为值
# responses中 以connection.fileno() 作为键 以相应的内容作为值,这个我们返回的是固定的,仅仅返回hello world requests[connection.fileno()] = b''
responses[connection.fileno()] = response # 如果请求的数据不是socketserver,那肯定是客户端的,判断是否是准备读的信号
elif event & select.EPOLLIN:
# 立马来开始读取数据,加到requests对象套接字的内容中去
requests[fileno] += connections[fileno].recv() # 判断换行 和 两个换行是否在接收过来的数据中
if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
# 如果是的话,就将这个套接字的监听更新为准备写
epoll.modify(fileno, select.EPOLLOUT) # 打印40个-,然后换行,加上请求的内容
print('-' * + '/n' + requests[fileno].decode()[:-])
# 如果请求的数据不是socketserver,那肯定是客户端的,判断是否是准备写的信号
elif event & select.EPOLLOUT:
# 立马来开始读取数据,就将response的对应的套接字号对应的值拿出来,其实就是hello world,O(∩_∩)O哈哈~
# 并统计发送了多少个字节
byteswritten = connections[fileno].send(responses[fileno])
# 更新response对应套接字内容为剩下的内容
responses[fileno] = responses[fileno][byteswritten:]
# 如果内容发完了,剩下的长度就是0,如果长度是0
if len(responses[fileno]) == :
# 就修改select,不监听该套接字的内容,其就变成了EPOLLHUP
epoll.modify(fileno, )
# 然后关闭该socket的管道
connections[fileno].shutdown(socket.SHUT_RDWR)
elif event & select.EPOLLHUP:
# 如果不监听该套接字的内容,就将其注销掉
epoll.unregister(fileno)
# 关闭该套接字
connections[fileno].close()
# 从连接中删除该文件描述符
del connections[fileno]
finally:
# 最后关闭serversocket服务器套接字
epoll.unregister(serversocket.fileno())
# 关闭epoll
epoll.close()
# 套接字关闭
serversocket.close()
python之epoll服务器源码分析的更多相关文章
- epoll(2) 源码分析
epoll(2) 源码分析 文本内核代码取自 5.0.18 版本,和上一篇文章中的版本不同是因为另一个电脑出了问题,但是总体差异不大. 引子留下的问题 关键数据结构 提供的系统调用 就绪事件相关逻辑 ...
- tiny web服务器源码分析
tiny web服务器源码分析 正如csapp书中所记,在短短250行代码中,它结合了许多我们已经学习到的思想,如进程控制,unix I/O,套接字接口和HTTP.虽然它缺乏一个实际服务器所具备的功能 ...
- [1]传奇3服务器源码分析一 LoginGate
服务端下载地址: 点击这里 网上基本上都有分析该源码的分析详解,如:请点击该链接,但容易晕,而且也不全!所以才有了本文! 一.首先来看服务端的LoginGate源码 先来张图比较让人容易理解
- trinitycore 魔兽服务器源码分析(三) 多线程相关
先看LockedQueue.h template <class T, typename StorageType = std::deque<T> >class LockedQue ...
- Python线程池ThreadPoolExecutor源码分析
在学习concurrent库时遇到了一些问题,后来搞清楚了,这里记录一下 先看个例子: import time from concurrent.futures import ThreadPoolExe ...
- trinitycore 魔兽服务器源码分析(二) 网络
书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...
- epoll内核源码分析
转载:https://www.nowcoder.com/discuss/26226?type=0&order=0&pos=27&page=1 /* * fs/eventpo ...
- trinitycore 魔兽服务器源码分析(一) 网络
trinitycore是游戏服务器的开源代码 许多玩家使用魔兽的数据来进行测试 ,使用它来假设魔兽私服. 官方网址 https://www.trinitycore.org/ 类似的还有mangos ...
- 基于python的ardrone control源码分析与心得
这里有一段python代码,可用于操控ardrone 2.0.实验室曾经借鉴用过,并添加了部分功能.如今复习一下,顺便理理python的相关知识点. #!/usr/bin/env python # A ...
随机推荐
- python_day5学习笔记
一.正则表达式 字符: \d 匹配任何十进制数:相当于类[0-9] \D 匹配任何非数字字符:相当于类[^0-9] \s 匹配任何空白字符:相当于类[ \t\n\r\f\v] \S 匹配任何非空 ...
- linux命令(2):grep命令
实例一: a.log文件内容如下: 从 a.log 文件中提取包含“WARNING”或”FATAL”,同时不包含“IGNOR”的行 grep -E 'WARNING|FATAL' a.log | gr ...
- Xshell 找到上次执行的命令
ctrl + p 返回上一次输入命令字符 ctrl + r 输入单词搜索历史命令
- NOIP模拟2017.6.11解题报告
T1: 水题: 代码: #include <cstdio> #include <iostream> #include <algorithm> using names ...
- Docker for Windows 里的Shared Drives 设置不生效
原文地址:传送门 问题描述:Docker中的settings里的Shared Drives 选择对应盘符后,点击Apply后无法生效,没办法选择对应盘符进行分享. 解决办法:win+R ,键入gped ...
- yum 安装
可以有两种方式:1.sudo yum install 然后输入root密码2.su root,输入密码然后yum install
- mysql ERROR 1366
mysql ERROR 1366 mysql> INSERT INTO tb_room VALUES ('9101','9','1',300,'9101',0,1,'超级豪华间','public ...
- HDU 6166 Senior Pan (最短路变形)
题目链接 Problem Description Senior Pan fails in his discrete math exam again. So he asks Master ZKC to ...
- 【转】Django中的cookie与session
转自:https://www.cnblogs.com/chenchao1990/p/5283725.html cookie与session的实现原理 HTTP被设计为”无状态”,每次请求都处于相同的空 ...
- python正则的中文处理(转)
匹配中文时,正则表达式规则和目标字串的编码格式必须相同 print sys.getdefaultencoding() text =u"#who#helloworld#a中文x#" ...