知识点:

    之前写的四种方法实现并发服务效率都还是低,早期的服务器采用的是select和poll方式,select这种方式的特点是轮询所有套接字去一个个看有没有事件发生,但是装套接字的列表长度是有限制的,而且轮询方式效率低,poll方式只是解决了装套接字这个列表的长度限制,但也是采用轮询的方式。目前实际场景中,linux服务器采用的都是epoll方案实现并发服务的,它解决了轮询这种低效率方式,采用事件通知的方式告诉应用程序哪个套接字发来了数据它的效率远远高于其他四种,它也是采用单进程单线程的方式,但是是堵塞的,主要有俩大特点:1、epoll方式会映射一个和操作系统一样的能处理应用程序的指定的文件描述符内存空间(即省去了将应用程序中的套接字文件描述符拷贝到操作系统中的过程),它既不属于应用程序也不属于操作系统 ,是俩个共用的的2、客户端套接字发送数据,epoll采用事件通知方式告诉应用程序,而不需要轮询所有的套接字列表

1、代码实现:

#!/usr/bin/env python
# coding=utf-8
# author:刘仲
# datetime:2018/8/6 9:24
# software: PyCharm import socket
import select
import re
"""之前写的四种方法实现并发服务效率都还是低,早期的服务器采用的是select和poll方式,select这种方式的特点是轮询所有套接字去
一个个看有没有事件发生,但是装套接字的列表是有限制的,而且轮询方式效率低,poll方式只是解决了装套接字这个列表的长度限制,
但也是采用轮询的方式。目前实际场景中,linux服务器采用的都是epoll方案实现并发服务的,它解决了轮询这种低效率方式,采用事件
通知的方式告诉应用程序哪个套接字发来了数据它的效率远远高于其他四种,它也是采用单进程单线程的方式,但是是堵塞的,主要有俩
大特点:1、epoll方式会映射一个和内核一样的能处理应用程序的事件的2、客户端套接字发送数据,内核的文件系统会采用事件通知的
方式告诉应用程序
""" def webserver():
web_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
web_socket.bind(('127.0.0.1', 7786))
web_socket.listen(128)
epl = select.epoll() # 创建epoll对象
epl.register(web_socket.fileno(), select.EPOLLIN | select.EPOLLET) # 将监听套接字注册到epl
fd_dict = dict() # 存放新的套接字的文件描述符和与之对应的套接字对象
while True:
epl_list = epl.poll() # 默认堵塞,获取注册到epl对象中的所有套接字列表,列表里存的是元祖,元祖俩个值分别对应的是
# 套接字的文件描述符和事件类型
for fd, event in epl_list: # 获取套接字的文件描述符和事件类型
if fd == web_socket.fileno(): # 刚开始epl_list肯定存放的是监听套接字,所以新的客户端链接进来,先判断文件描述符是否等与监听套接字的文件描述符 new_socket, new_adress = web_socket.accept() # 新客户端链接进来进行解堵塞
fd_dict[new_socket.fileno()] = new_socket # 将新的客户端套接字的文件描述符和与之对应的套接字存放到字典中
epl.register(new_socket.fileno(), select.EPOLLIN) # 将新的套接字注册到epl中
elif event == select.EPOLLIN: # 当监听事件触发,即客户端发来数据
try:
data = fd_dict[fd].recv(1024).decode('utf-8')
except:
print('客户端没有发送数据')
else:
if data:
data1 = data.splitlines()
request_url = re.match(r"[^/]+(/[^ ]*)",data1[0])
if request_url:
file_name = request_url.group(1)
if file_name == '/': file_name = '/index.html'
try:
body = open('./html'+file_name, 'rb')
except:
response_head = 'HTTP 404 NOT FOUND/1.1\r\n'
response_head += '\r\n'
response_body = '<h1>NOT FOUND PAGE</H1>'
fd_dict[fd].send((response_head + response_body).encode('utf-8'))
else:
response_body = body.read()
body.close()
response_head = 'HTTP 200 OK/1.1\r\n'
response_head += 'Content-Length:%d\r\n'%len(response_body)
response_head += '\r\n'
fd_dict[fd].send(response_head.encode('utf-8')+response_body)
fd_dict[fd].close() else: fd_dict[fd].close() # 关闭新的套接字
epl.unregister(fd) # 从epl中移除该文件描述符的链接
del fd_dict[fd] # 删除这个套接字的键值对
web_socket.close() if __name__ == '__main__':
webserver()

web服务-3、epoll高效率实现并发服务器的更多相关文章

  1. Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)(转)

    转自:http://blog.csdn.net/wuyuxing24/article/details/48758927 一, 背景 先说下我要实现的功能,server端一直在linux平台下面跑,当客 ...

  2. 基于线程池、消息队列和epoll模型实现并发服务器架构

    引言 并发是什么?企业在进行产品开发过程中为什么需要考虑这个问题?想象一下天猫的双11和京东的618活动,一秒的点击量就有几十万甚至上百万,这么多请求一下子涌入到服务器,服务器需要对这么多的请求逐个进 ...

  3. Angular内提供了一个可以快速建立测试用web服务的方法:内存 (in-memory) 服务器

    如何使用 Angular 内存 (in-memory) 服务器https://segmentfault.com/a/1190000009898540

  4. nginx web服务优化

    nginx基本安全优化 1. 调整参数隐藏nginx软件版本号信息 软件的漏洞和版本有关,我们应尽量隐藏或消除web服务对访问用户显示各类敏感信息(例如web软件名称及版本号等信息),这样恶意的用户就 ...

  5. linux web服务基础知识,dns

    #web服务基础知识c/s 客户端/服务器b/s 浏览器/服务器 nginx   >   web  server  服务端浏览器  >    web  client  客户端 #dns解析 ...

  6. golang 简单web服务

    1.golang print输入 package main import "fmt" func main() { fmt.Printf("Hello World!\n&q ...

  7. LINUX环境并发服务器的三种实现模型

    服务器设计技术有很多,按使用的协议来分有TCP服务器和UDP服务器.按处理方式来分有循环服务器和并发服务器. 1  循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器,为了 ...

  8. 如何读懂Web服务的系统架构图

    Web服务的一个重要特点就是流量大.数据多,仅靠一台服务器肯定难以支撑大规模的服务. 所以我们经常会看到诸如以下的一些术语,教人好生不懂: *:系统架构.物理架构.Web服务基础设施 *:应用服务器 ...

  9. web服务-2、四种方法实现并发服务器-多线程,多进程,协程,(单进程-单线程-非堵塞)

    知识点:1.使用多线程,多进程,协程完成web并发服务器 2.单进程-单线程-非堵塞也可以实现并发服务器 1.多进程和协程的代码在下面注释掉的部分,我把三种写在一起了 import socket im ...

随机推荐

  1. Swagger如何测试Date类型参数

    问题 Swagger测试时,参数直接输入日期格式化后的类型,会报参数日期转换错误 :ConversionFailedException 解决 网上说在参数上添加注解 @DateTimeFormat(p ...

  2. 洛谷 P2042 【[NOI2005]维护数列】

    一直在想要做这道题,但是被那个硕大的Splay标签压垮了 好了,切入正题 这道题应该是我第二次用splay来维护区间问题 我还是太菜了QAQ 其实思路也很简单,就是以每一个位置的下标来进行维护,然后其 ...

  3. 深入理解JVM(2)——运行时数据区

    1.运行时数据区 1.1.程序计数器 记录当前线程正在执行的字节码指令的地址,如果正在执行的是 Native 方法,这个计数器值则为空. 1.2.虚拟机栈 每个 Java 方法在执行的同时会创建一个栈 ...

  4. 初识 go 语言:方法,接口及并发

    目录 方法,接口及并发 方法 接口 并发 信道 结束语 前言: go语言的第四篇文章,主要讲述go语言中的方法,包括指针,结构体,数组,切片,映射,函数闭包等,每个都提供了示例,可直接运行. 方法,接 ...

  5. python+turtle 笔记

    用Python+turtle绘制佩琪: from turtle import * def nose(x,y):#鼻子 penup()#提起笔 goto(x,y)#定位 pendown()#落笔,开始画 ...

  6. 【原创】支持同时生成多个main函数 makefile 模板

    背景: 去年做项目的时候,由于有需要编译出多个可执行文件的需求,修改了Makefile使其支持生成多个结果(编译多个含有main函数的文件),但总觉得自己的实现不够完美. 今年又遇到这样需求的时候,可 ...

  7. Elasticsearch 6.4基本操作 - Java版

    1. Elasticsearch Java API有四类client连接方式 TransportClient RestClient Jest Spring Data Elasticsearch 其中T ...

  8. MySQL的一些基本命令笔记(4)

    delete 语句嵌套子查询: delete from 表名1 where 列名 操作符 (select 列名 from 表名2 where 条件); 示例: delete from customer ...

  9. 《我是一只IT小小鸟读后感》

    在我步入大学前,并未了解何为IT,真是毫无知晓.由于种种原因最终还是选择了软件工程专业,是 对是错,是福是祸,不知该不该去考虑,但即已然 选择了这条路,便得付出一些努力,这个世界总 是有许多在默默努力 ...

  10. Windows下VSCode编译调试c/c++

    参考链接:  https://blog.csdn.net/c_duoduo/article/details/51615381 支持makefile编译: https://www.cnblogs.com ...