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服务器的更多相关文章

  1. 用python实现自己的http服务器——多进程、多线程、协程、单进程非堵塞版、epoll版

    了解http协议 http请求头 GET / HTTP/1.1 Host: www.baidu.com Connection: keep-alive Pragma: no-cache Cache-Co ...

  2. 第十八篇:简易版web服务器开发

    在上篇有实现了一个静态的web服务器,可以接收web浏览器的请求,随后对请求消息进行解析,获取客户想要文件的文件名,随后根据文件名返回响应消息:那么这篇我们对该web服务器进行改善,通过多任务.非阻塞 ...

  3. epoll 回显服务器源码

    在写epoll回显服务器代码之前,可以先看看上一篇文章:select poll epoll三者之间的比较.最近在继续学习网络编程中的服务端编程中,了解到很多网游服务器是在IOMP(IO完成端口)框架下 ...

  4. Ubuntu桌面版与服务器版有什么不同?

         提到安装Linux,Ubuntu可谓是最受欢迎的.为了满足每个人的需求,出现了不少版本或风格的Ubuntu;其中两项便是桌面版与服务器版.只要发布版本号一致,这两者从核心来说也就是相同的,唯 ...

  5. Java NIO系列教程(七) selector原理 Epoll版的Selector

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  6. Go语言之进阶篇简单版并发服务器

    1.简单版并发服务器 示例1: package main import ( "fmt" "net" "strings" ) //处理用户请求 ...

  7. 【Networking】(转)一个非常好的epoll+线程池服务器Demo

    (转)一个非常好的epoll+线程池服务器Demo Reply 转载自:http://zhangyafeikimi.javaeye.com/blog/285193 [cpp] /** 张亚霏修改 文件 ...

  8. Ubuntu桌面版与服务器版的区别(转)

    Ubuntu桌面版vs服务器版 提到安装Linux,Ubuntu可谓是最受欢迎的.为了满足每个人的需求,出现了不少版本或风格的Ubuntu:其中两项便是桌面版与服务器版.只要发布版本号一致,这两者从核 ...

  9. PHP环境配置-从Apache官网下载windows版apache服务器

    由于个人有强迫倾向,下载软件都喜欢从官网下载,摸索了好久终于摸清楚怎么从Apache官网下载windows安装版的Apache服务器了,现在分享给大家. 进入apache服务器官网http://htt ...

随机推荐

  1. TCP/IP学习笔记15--IP分割处理与再构成处理,路径MTU发现

           家庭应该是爱.欢乐和笑的殿堂.--日 木村久一        IP属于网络层,下一层时数据链路层,在数据链路层,不同类型的数据链路的最大传输单元(MTU)都不尽相同.例如,连接两个路由器 ...

  2. Selenium 配置IE浏览器

    1.安装selenium pip install selenium 2.安装IE浏览器driver http://selenium-release.storage.googleapis.com/ind ...

  3. [洛谷P4213]【模板】杜教筛(Sum)

    题目大意:给你$n$,求:$$\sum\limits_{i=1}^n\varphi(i),\sum\limits_{i=1}^n\mu(i)$$最多$10$组数据,$n\leqslant2^{31}- ...

  4. [洛谷P3227][HNOI2013]切糕

    题目大意:有一个$n\times m$的切糕,每一个位置的高度可以在$[1,k]$之间,每个高度有一个代价,要求四联通的两个格子之间高度最多相差$D$,问可行的最小代价.$n,m,k,D\leqsla ...

  5. BZOJ5104 Fib数列 二次剩余、BSGS

    传送门 发现只有通项公式可以解决考虑通项公式 \(F_n = \frac{1}{\sqrt{5}}((\frac{1+\sqrt{5}}{2})^n - (\frac{1-\sqrt{5}}{2})^ ...

  6. go 学习笔记(4) package

    package name 尽量与目录名称一样 package name: 表示代码文件所属的包

  7. IIS初始化设置预加载,解决程序池被回收第一次访问慢问题

    问题现象: 部署到IIS上的项目,第一次访问比较慢,有时后空闲一段时间去访问也会很慢,经常隔天访问也会慢.这就是IIS回收导致的问题,IIS回收把程序池的内存释放,网站就相当与重启的状态,被回收后,我 ...

  8. C#精粹--协变和逆变

    概念 协变和逆变来源于类型和类型之间的绑定,C#4.0开始在泛型的接口和委托上支持协变和逆变,不过在这个版本之前的委托也是支持协变和逆变的.比如数组就支持协变,但是这不是一个好的特性,这C#初期版本从 ...

  9. oracle 查询 10题

    说明:表数据来自oracle 初始用户之一scott里面的三个初始表:emp,dept,salgrade --1.查询员工表中工资最高的雇员的员工号.员工姓名.工资和部门号. select empno ...

  10. Flutter 实现图片裁剪

    实现原理很简单 ,自己绘制一个裁剪框, 根据手势 选择到适合的位置 ,然后将选中的区域绘制到一个新的图片上,从而完成裁剪 裁剪框的绘制  这里我是根据点来连线的  因为每个点上会绘制一个拉伸的标识符 ...