epoll版http服务器
epoll是事件通知方式接收数据,效率比轮询要高
代码:
import socket
import re
import select def client_server(new_client,recv_data):
# 接收客户端请求
# recv_data = new_client.recv(1024).decode("utf-8")
# 把读出的数据分行
recv_data_lines = recv_data.splitlines()
# 正则匹配GET后面的请求的页面
# [^/]表示非“/”字符 +表示至少1个或多个,[^ ]只要不是空格,*表示0个或多个
ret = re.match(r"[^/]+(/[^ ]*)",recv_data_lines[0]) # ret = re.search(r"/[^ ]*",recv_data_lines[0]) # 查找第一次“/”后面非空格的字符串
file_name = ret.group(1)
# 打开文件
try:
f = open("./html" + file_name,"rb")
except:
# 创建返回数据 HEADER
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "\r\n"
response += "-----NOT FOUND----"
# 发送数据到客户端
new_client.send(response.encode("utf-8"))
else:
# 读出数据
html_content = f.read()
# 把读出的数据放到BODY体里面
response_body = html_content # 创建返回数据 HEADER
response_header = "HTTP/1.1 200 ok\r\n"
# 告诉浏览器发送过去的长度
response_header += "Content-Length:%d\r\n" % len(response_body)
response_header += "\r\n"
# 把HEADER和BODY拼接在一起
response = response_header.encode("utf-8") + response_body
# 发送数据到客户端
new_client.send(response) # 关闭套接字 长链接不要关闭此套接字 等客户端关闭
# new_client.close() def main():
# 创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 设置当服务器先调用close() 即服务器4次回收之后资源能够立即释放,这样就保证了下次运行程序时,可以立即使用
# SO_REUSEADDR重复使用地址
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 绑定端口
tcp_server_socket.bind(("",7890))
# 设置监听状态
tcp_server_socket.listen(128)
# 设置非堵塞
tcp_server_socket.setblocking(False) # 创建一个epoll对象
epl = select.epoll() # 将监听套接字对应的fd注册到epoll中
# select.EPOLLIN监听是否有数据输入
epl.register(tcp_server_socket.filno(),select.EPOLLIN) # 新建socket存储字典
fd_event_dic = dict() # 新建为客户端服务的套接字
while True:
# poll()默认会堵塞 直到os监测到数据到来 通过事件通知方式 告诉这个程序 才会解堵塞 有返回值 返回值是列表
fd_event_list = epl.poll() #[(fd,event),(套接字对应的文件描述符,这个文件描述符是什么事件 例如 可以调用recv()接收等)]
for fd, event in fd_event_list:
# 判断fd如果是监听套接字的fd
if fd == tcp_server_socket.fileno():
# 创建客户端套接字,接收客户端地址
new_client, client_addr = tcp_server_socket.accept()
# 将客户端套接字fd注册到epoll中
epl.register(new_client.fileno(), select.EPOLLIN)
# 将客户端套接字存储到字典
fd_event_dic[new_client.fileno()] = new_client
# 如果不是监听套接字的fd或者是事件通知
elif event == select.EPOLLIN:
recv_data = fd_event_dic[fd].recv(1024).decode("utf-8")
# 如果有数据
if recv_data:
# 调用client_server
client_server(fd_event_dic[fd], recv_data)
# 如果是空数据
else:
# 调用客户端套接字close()
fd_event_dic[fd].close()
# 注销在epoll中的客户端套接字fd
epl.unregister(fd)
# 移出字典
del fd_event_dic[fd] # 关闭套接字
tcp_server_socket.close() if __name__ == '__main__':
main()
epoll版http服务器的更多相关文章
- 用python实现自己的http服务器——多进程、多线程、协程、单进程非堵塞版、epoll版
了解http协议 http请求头 GET / HTTP/1.1 Host: www.baidu.com Connection: keep-alive Pragma: no-cache Cache-Co ...
- 第十八篇:简易版web服务器开发
在上篇有实现了一个静态的web服务器,可以接收web浏览器的请求,随后对请求消息进行解析,获取客户想要文件的文件名,随后根据文件名返回响应消息:那么这篇我们对该web服务器进行改善,通过多任务.非阻塞 ...
- epoll 回显服务器源码
在写epoll回显服务器代码之前,可以先看看上一篇文章:select poll epoll三者之间的比较.最近在继续学习网络编程中的服务端编程中,了解到很多网游服务器是在IOMP(IO完成端口)框架下 ...
- Ubuntu桌面版与服务器版有什么不同?
提到安装Linux,Ubuntu可谓是最受欢迎的.为了满足每个人的需求,出现了不少版本或风格的Ubuntu;其中两项便是桌面版与服务器版.只要发布版本号一致,这两者从核心来说也就是相同的,唯 ...
- Java NIO系列教程(七) selector原理 Epoll版的Selector
目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...
- Go语言之进阶篇简单版并发服务器
1.简单版并发服务器 示例1: package main import ( "fmt" "net" "strings" ) //处理用户请求 ...
- 【Networking】(转)一个非常好的epoll+线程池服务器Demo
(转)一个非常好的epoll+线程池服务器Demo Reply 转载自:http://zhangyafeikimi.javaeye.com/blog/285193 [cpp] /** 张亚霏修改 文件 ...
- Ubuntu桌面版与服务器版的区别(转)
Ubuntu桌面版vs服务器版 提到安装Linux,Ubuntu可谓是最受欢迎的.为了满足每个人的需求,出现了不少版本或风格的Ubuntu:其中两项便是桌面版与服务器版.只要发布版本号一致,这两者从核 ...
- PHP环境配置-从Apache官网下载windows版apache服务器
由于个人有强迫倾向,下载软件都喜欢从官网下载,摸索了好久终于摸清楚怎么从Apache官网下载windows安装版的Apache服务器了,现在分享给大家. 进入apache服务器官网http://htt ...
随机推荐
- VS+OpenGl 显示三维STL模型 代码
今天调出了用VS环境结合OpenGL glut工具包进行显示STL模型的模块,进行了渲染.效果: 如下,后期会进行进一步优化,先贴上: #ifndef DATA_H #define DATA_H st ...
- js 获取服务端时间,并实现时钟
本例子以vue语法伪代码书写: 1,获取服务端北京时间 getRealTime() { let that = this; var xhr = new XMLHttpRequest(); if( !xh ...
- sync包 — 汇总
sync包 package main; import ( "time" "fmt" ) func main() { //time.Time代表一个纳秒精度的时间 ...
- Spark源码(1) Spark配置
写熟悉的第一句代码 val conf = new SparkConf().setAppName("WordCount")点击SparkConf() ,发现 private val ...
- VS2015如何在同一个解决方案下建立多个项目
1.先按照常规的方法建一个项目: 2.点击解决方案:右键=>添加=>新建项目 注:本文链接:https://blog.csdn.net/weixin_43081805/article/de ...
- CF13C Sequence(DP+离散化)
题目描述 给定一个序列,每次操作可以把某个数+1-1.要求把序列变成非降数列.求最少的修改次数. 输入输出样例 输入 #1 - 输出 #1 4 输入 #2 输出 #2 1 解题思路 这题是一道非常好题 ...
- 11 IO流(八)——装饰器设计模式,Filter装饰流
声明:本文部分图片及内容引用自:https://www.cnblogs.com/qiumingcheng/p/5219631.html java装饰器设计模式 举一个形象的例子,人可以说话,而扩音器可 ...
- go语言学习笔记---读取文件io/ioutil 包
io/ioutil 包几个函数方法 名称 作用 备注 ReadAll 读取数据,返回读到的字节 slice 1 ReadDir 读取一个目录,返回目录入口数组 []os.FileInfo, 2 Re ...
- 8 search中的timeout参数
默认的search,是没有时间限制的.比如,一个search,可能要10分钟才能搜完,那么,es就会等10分钟,直到结果出来. 然而,在某些场景下,客户是等不了10分钟的.比如,电商网站,客户宁可 ...
- UCOSIII事件标志组
两种同步机制 "或"同步 "与"同步 使能 #define OS_CFG_FLAG_EN 1u /* Enable (1) or Disable (0) cod ...