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 ...
随机推荐
- Dubbo 用户手册学习笔记 —— Dubbo架构
Dubbo的架构 节点角色说明 节点 角色说明 Provider 服务提供方 Consumer 服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和调用时间的监 ...
- C入门之一
1.stdio.h不要写错成studio.h 2. #include <stdio.h> int main() { /* 我的第一个 C 程序 */ printf("Hello, ...
- initWithFrame和initWithCoder的区别
如果使用了Interface Builder 方式或nib,就不会调用initWithFrame方法,因为nib文件知道怎么初始化了, 但可以使用initWithCoder这一个更深层的init方法来 ...
- redis之(十五)redis的集群中的哨兵角色
一:redis集群的哨兵的目的是什么?. (1)监控主redis和从redis数据库是否正常运行 (2)主redis出现故障,自动将其中一台从redis升级为主redis.将原先的主redis转变成从 ...
- 数据库索引(Index)【未完待续】
数据库索引是啥?有什么用?原理是什么?最佳实践什么? 索引是啥 一个索引是这样的数据结构:从数据上来说,不仅包含了从表中某一列或多列的数据拷贝,同时,还包含了指向这列数据行的链接: 从结构上来说,索引 ...
- JavaScript 闭包(随笔)
闭包,伟大的闭包.... 先看看百科对百度的定义是什么样的. 百科说:闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境 ...
- HDU 5127.Dogs' Candies-STL(vector)神奇的题,set过不了 (2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大))
周六周末组队训练赛. Dogs' Candies Time Limit: 30000/30000 MS (Java/Others) Memory Limit: 512000/512000 K ( ...
- python No migrations to apply
错误显示: “No migrations to apply” 错误情况:python在通过model同步数据库时,提示 No migrations to apply 查看数据库,新表没有被创建,只是 ...
- PLSQL的注释技巧
概述 这里提供一些注释的技巧,用来模仿Java中的文档注释的功能. 在Eclipse中,鼠标悬浮在类或其成员上,会显示相关的文档注释:在PL/SQL中也有类似的功能,我们需要掌握一些注释技巧,让其可读 ...
- Shiro源码分析之Subject和SecurityManager
Subject 毫无疑问,Subject是Shiro最重要的一个概念. “Subject”只是一个安全术语,意味着应用程序用户的特定于安全性的“视图”.Shiro Subject实例代表单个应用程序用 ...