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 ...
随机推荐
- 使用nohup命令编写shell脚本启动java应用,并使用外挂配置文件
nohup nohup命令:如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令.该命令可以在你退出帐户/关闭终端之后继续运行相应的进程. 在缺省情况下该作业的所 ...
- pymysql 模块简单使用
目录 pymysql 模块简单使用 安装 pymysql 模块 使用 pymysql 连接数据库 并插入数据 使用pymysql 插入数据 修改查询显示结果 pymysql 模块简单使用 安装 pym ...
- 安装 go和beego后的环境变量设置
简介 之前有几次因为环境变量设置的问题 损失了一些时间,特在此做记录 安装golang 可参考官方Getting Started,但有时候有问题. 解压 tar -C /usr/local -xzf ...
- L2R 二:常用评价指标之AUC
零零散散写了一些,主要是占个坑: AUC作为一个常用的评价指标,无论是作为最后模型效果评价还是前期的特征选择,都发挥着不可替代的作用,下面我们详细介绍下这个指标. 1.定义 2.实现 # coding ...
- java之结合代码理解synchronized关键字
为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制.synchronized关键字是最基本的互斥同步手段.除此之外,还可以使用java.util.concurrent包中的重入锁 ...
- Java线程volatile(二)
volatile:使变量在多个线程中可见 在java 中每个线程都会有一块工作内存区,其中存放着所有线程共享的主内存中变量的拷贝.当线程执行时,在自己的工作内存区操作这些变量,为了存取一个共享的变量, ...
- Linux 中ifconfig和ip addr命令看不到ip
解决方案: 输入 vi /etc/sysconfig/network-scripts/ifcfg-ens33 将ONBOOT权限改为yes 保存退出,按Esc,输入:wq 重启网络服务,输入 sudo ...
- MySQL事务和事务隔离级别
1.概述 事务就是对数据库数据进行更改(包括insert.update.delete等)操作的一个执行单元,通常有一条或多条更改语句组成.在同一个事务中的更改操作要么同时成功,要么同时失败. 事务具有 ...
- js --装饰者模式
定义 装饰者模式能够在补改变对象自身的基础上,在程序运行期间给对象动态的添加职责. 当看到装饰者模式的定义的时候,我们想到的js 的三大特性之一--继承,不也能够实现不改变对象自身的基础上,添加动态的 ...
- Part_three:Redis持久化存储
redis持久化存储 Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,Redis提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失. 1.RD ...