#!/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服务器源码分析的更多相关文章

  1. epoll(2) 源码分析

    epoll(2) 源码分析 文本内核代码取自 5.0.18 版本,和上一篇文章中的版本不同是因为另一个电脑出了问题,但是总体差异不大. 引子留下的问题 关键数据结构 提供的系统调用 就绪事件相关逻辑 ...

  2. tiny web服务器源码分析

    tiny web服务器源码分析 正如csapp书中所记,在短短250行代码中,它结合了许多我们已经学习到的思想,如进程控制,unix I/O,套接字接口和HTTP.虽然它缺乏一个实际服务器所具备的功能 ...

  3. [1]传奇3服务器源码分析一 LoginGate

    服务端下载地址: 点击这里 网上基本上都有分析该源码的分析详解,如:请点击该链接,但容易晕,而且也不全!所以才有了本文! 一.首先来看服务端的LoginGate源码 先来张图比较让人容易理解

  4. trinitycore 魔兽服务器源码分析(三) 多线程相关

    先看LockedQueue.h template <class T, typename StorageType = std::deque<T> >class LockedQue ...

  5. Python线程池ThreadPoolExecutor源码分析

    在学习concurrent库时遇到了一些问题,后来搞清楚了,这里记录一下 先看个例子: import time from concurrent.futures import ThreadPoolExe ...

  6. trinitycore 魔兽服务器源码分析(二) 网络

    书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...

  7. epoll内核源码分析

    转载:https://www.nowcoder.com/discuss/26226?type=0&order=0&pos=27&page=1 /*  *  fs/eventpo ...

  8. trinitycore 魔兽服务器源码分析(一) 网络

    trinitycore是游戏服务器的开源代码 许多玩家使用魔兽的数据来进行测试 ,使用它来假设魔兽私服. 官方网址  https://www.trinitycore.org/ 类似的还有mangos ...

  9. 基于python的ardrone control源码分析与心得

    这里有一段python代码,可用于操控ardrone 2.0.实验室曾经借鉴用过,并添加了部分功能.如今复习一下,顺便理理python的相关知识点. #!/usr/bin/env python # A ...

随机推荐

  1. python_day5学习笔记

    一.正则表达式 字符: \d 匹配任何十进制数:相当于类[0-9] \D 匹配任何非数字字符:相当于类[^0-9] \s  匹配任何空白字符:相当于类[  \t\n\r\f\v] \S  匹配任何非空 ...

  2. linux命令(2):grep命令

    实例一: a.log文件内容如下: 从 a.log 文件中提取包含“WARNING”或”FATAL”,同时不包含“IGNOR”的行 grep -E 'WARNING|FATAL' a.log | gr ...

  3. Xshell 找到上次执行的命令

    ctrl + p   返回上一次输入命令字符 ctrl + r       输入单词搜索历史命令

  4. NOIP模拟2017.6.11解题报告

    T1: 水题: 代码: #include <cstdio> #include <iostream> #include <algorithm> using names ...

  5. Docker for Windows 里的Shared Drives 设置不生效

    原文地址:传送门 问题描述:Docker中的settings里的Shared Drives 选择对应盘符后,点击Apply后无法生效,没办法选择对应盘符进行分享. 解决办法:win+R ,键入gped ...

  6. yum 安装

    可以有两种方式:1.sudo yum install 然后输入root密码2.su root,输入密码然后yum install

  7. mysql ERROR 1366

    mysql ERROR 1366 mysql> INSERT INTO tb_room VALUES ('9101','9','1',300,'9101',0,1,'超级豪华间','public ...

  8. HDU 6166 Senior Pan (最短路变形)

    题目链接 Problem Description Senior Pan fails in his discrete math exam again. So he asks Master ZKC to ...

  9. 【转】Django中的cookie与session

    转自:https://www.cnblogs.com/chenchao1990/p/5283725.html cookie与session的实现原理 HTTP被设计为”无状态”,每次请求都处于相同的空 ...

  10. python正则的中文处理(转)

    匹配中文时,正则表达式规则和目标字串的编码格式必须相同 print sys.getdefaultencoding() text =u"#who#helloworld#a中文x#" ...