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()

最新文章

  1. AAU
  2. 浏览器-08 chromium 渲染2
  3. [Android Tips] 23. How to fail/stop Gradle task immediately if some conditions are not met
  4. iOS-ARC项目使用非ARC文件 MRC项目使用ARC文件
  5. jQuery Form 表单提交插件----Form 简介,官方文档,官方下载地址
  6. ThinkPHP 3.2.2跨控制器调用方法
  7. 四.CSS声明
  8. bootstrap兼容IE
  9. 一些方便的bash命令
  10. 学python走过的坑 三 不能实现的浏览器缩放功能
  11. 多个vlan之间路由
  12. LAB8 android
  13. Improved SEO with mod_rewrite
  14. JavaScript:原生JS实现Facebook实时消息抓捕
  15. 对List数组进行排序 Collections.sort(param1,param2)
  16. SecureCRT突然卡死的问题
  17. KVM源代码解读:linux-3.17.4\arch\x86\include\asm\kvm_host.h
  18. PPT汇报 评审表
  19. 【知了堂学习笔记】java web 简单的登录
  20. 64位ubuntu下用code::blocks IDE配置opengl开发环境

热门文章

  1. 轮胎魔术公式(Magic Fomula)模型
  2. Java大厂笔试&&面试集合大全目录
  3. SQL——WHERE子句
  4. 《Docker Deep Dive》Note - 纵观 Docker
  5. Scala 函数入门之过程、lazy值和异常
  6. python多线程一些知识点梳理
  7. SQL Server中,常用的全局变量
  8. java之struts2的数据处理
  9. Java Swing 资料(转载学习)
  10. NEST explain