知识点:

    之前写的四种方法实现并发服务效率都还是低,早期的服务器采用的是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. 2.8 hashlib模块

  2. python实现域名解析和归属地查询

    前言工作中有时要查询域名解析和获取域名相关IP归属地信息 安装依赖python2:pip install dnspythonpython3:python3 -m pip install -i http ...

  3. 了解PID控制

    @2019-03-07 [小记] 了解PID控制 比例 - 积分 - 微分 积分 --- 记忆过去 比例 --- 了解现在 微分 --- 预测未来

  4. 【dp】求最长上升子序列

    题目描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.我们想知道此时最长上升子序列长度是多少? 输入 第一行一个整数N,表示我们要将1到N插入序列中 ...

  5. CF908D New Year and Arbitrary Arrangement(期望Dp+数学)

    题目大意:给你一个空字符串,你有\(\frac{pa}{pa+pb}\)的概率往字符串最后面加个\(a\),\(\frac{pb}{pa+pb}\)的概率往字符串最后面加个\(b\),当子序列\(ab ...

  6. python学习day12 函数Ⅳ (闭包&内置模块)

    函数Ⅳ (闭包&内置模块) 1.内置函数(补充) lambda表达式也叫匿名函数. 函数与函数之间的数据互不影响,每次运行函数都会开一个辟新的内存. item = 10 def func(): ...

  7. Dubbo2.6.5入门——管控台的安装

    首先去下载管控台:GitHub 然后解压到本地,截止到目前2019-01-18,最新管控台基于Dubbo2.7.0-SNAPSHOT版本,但是2.7.0还没有正式发布,不过影响不大. Dubbo Op ...

  8. Pandas系列(六)-时间序列详解

    内容目录 1. 基础概述 2. 转换时间戳 3. 生成时间戳范围 4. DatetimeIndex 5. DateOffset对象 6. 与时间序列相关的方法 6.1 移动 6.2 频率转换 6.3 ...

  9. Spring Security 之基本概念

    Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Spring S ...

  10. @RequestParam,@PathParam,@PathVariable等注解区别

    @RequestParam 和 @PathVariable 注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @P ...