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 ...
随机推荐
- Spring Boot取消默认tomcat启动,打成war包发布到服务器运行
一.设置打包方式 在pom.xml中设置打包格式 <packaging>war</packaging> 二.取消Spring Boot的tomcat <!--部署成war ...
- MapReduce Join关联
Reduce join 原理 Map端的主要工作:为来自不同表(文件)的key/value对打标签以区别不同来源的记录.然后用连接字段作为key,其余部分和新加的标志作为value,最后进行输出. R ...
- crontab 定时删除
/60 * * * /bin/find /usr/local/****/****/****/****/****.log.2019* -exec rm -f {} ; >/dev/null 2&g ...
- mysql sql 分析
一.SQL 执行时间分析通过找到执行时间长的 SQL 语句,可以直观的发现数据层的效率问题. 1.通过 show processlist 来查看系统的执行情况mysql> show proces ...
- promethus监控nginx
一.摘要 promethues监控nginx可选两个exporter,通过nginx_exporter主要是获取nginx-status中的内建的指标,nginx自身提供status信息,较为简单,p ...
- python基础_mysql建表、编辑、删除、查询、更新
1.建一张学生表 包含(id,name,age,sex)2.增加四条数据3.查询表中sex为男的数据4.删除id =3的数据,5.将sex为女的,修改为男 create: CREATE TABLE d ...
- Springboot 结合百度IORC实现自定义模板图片识别
前言: 首先呢,最近再公司的项目当中遇到这样的一个问题,就是需要识别图片,提取图片当中的关键语句,而且识别的语句当然是人家手写体识别,翻来覆去一想,最终还是决定使用百度的OCR帮助我解决这一项需求 话 ...
- HTTP API 认证授权术
原文:https://coolshell.cn/articles/19395.html 我们知道,HTTP是无状态的,所以,当我们需要获得用户是否在登录的状态时,我们需要检查用户的登录状态,一般来说, ...
- 虚拟机与宿主机可以互相ping通,但是外网不能
http://rickcheung.blog.51cto.com/913220/354429 1.CentOS 修改DNS 修改对应网卡的DNS的配置文件 # vi /etc/resolv.conf ...
- js 算法,判断一个数组中的数字出现多少次
let arr = [11, 11, 2, 2, 5, 5, 5, 5, 3]; //创建一个map,把每个数字和其个数相对应 let countObj = {}; for (i = 0; i < ...