zoukankan      html  css  js  c++  java
  • epoll版http服务器

    epoll是事件通知方式接收数据,效率比轮询要高

    代码:

      1 import socket
      2 import re
      3 import select
      4 
      5 
      6 def client_server(new_client,recv_data):
      7     # 接收客户端请求
      8     # recv_data = new_client.recv(1024).decode("utf-8")
      9     # 把读出的数据分行
     10     recv_data_lines = recv_data.splitlines()
     11     # 正则匹配GET后面的请求的页面
     12     # [^/]表示非“/”字符 +表示至少1个或多个,[^ ]只要不是空格,*表示0个或多个
     13     ret = re.match(r"[^/]+(/[^ ]*)",recv_data_lines[0])
     14 
     15     # ret = re.search(r"/[^ ]*",recv_data_lines[0])  # 查找第一次“/”后面非空格的字符串
     16     file_name = ret.group(1)
     17     # 打开文件
     18     try:
     19         f = open("./html" + file_name,"rb")
     20     except:
     21         # 创建返回数据 HEADER
     22         response = "HTTP/1.1 404 NOT FOUND
    "
     23         response += "
    "
     24         response += "-----NOT FOUND----"
     25         # 发送数据到客户端
     26         new_client.send(response.encode("utf-8"))
     27     else:
     28         # 读出数据
     29         html_content = f.read()
     30         # 把读出的数据放到BODY体里面
     31         response_body = html_content
     32 
     33         # 创建返回数据 HEADER
     34         response_header = "HTTP/1.1 200 ok
    "
     35         # 告诉浏览器发送过去的长度
     36         response_header += "Content-Length:%d
    " % len(response_body)
     37         response_header += "
    "
     38         # 把HEADER和BODY拼接在一起
     39         response = response_header.encode("utf-8") + response_body
     40         # 发送数据到客户端
     41         new_client.send(response)
     42 
     43     # 关闭套接字 长链接不要关闭此套接字 等客户端关闭
     44     # new_client.close()
     45 
     46 
     47 def main():
     48     # 创建套接字
     49     tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     50     # 设置当服务器先调用close() 即服务器4次回收之后资源能够立即释放,这样就保证了下次运行程序时,可以立即使用
     51     # SO_REUSEADDR重复使用地址
     52     tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
     53     # 绑定端口
     54     tcp_server_socket.bind(("",7890))
     55     # 设置监听状态
     56     tcp_server_socket.listen(128)
     57     # 设置非堵塞
     58     tcp_server_socket.setblocking(False)
     59 
     60     # 创建一个epoll对象
     61     epl = select.epoll()
     62 
     63     # 将监听套接字对应的fd注册到epoll中
     64     # select.EPOLLIN监听是否有数据输入
     65     epl.register(tcp_server_socket.filno(),select.EPOLLIN)
     66 
     67     # 新建socket存储字典
     68     fd_event_dic = dict()
     69 
     70     # 新建为客户端服务的套接字
     71     while True:
     72         # poll()默认会堵塞 直到os监测到数据到来 通过事件通知方式 告诉这个程序 才会解堵塞  有返回值 返回值是列表
     73         fd_event_list = epl.poll()
     74 
     75         #[(fd,event),(套接字对应的文件描述符,这个文件描述符是什么事件 例如 可以调用recv()接收等)]
     76         for fd, event in fd_event_list:
     77             # 判断fd如果是监听套接字的fd
     78             if fd == tcp_server_socket.fileno():
     79                 # 创建客户端套接字,接收客户端地址
     80                 new_client, client_addr = tcp_server_socket.accept()
     81                 # 将客户端套接字fd注册到epoll中
     82                 epl.register(new_client.fileno(), select.EPOLLIN)
     83                 # 将客户端套接字存储到字典
     84                 fd_event_dic[new_client.fileno()] = new_client
     85                 # 如果不是监听套接字的fd或者是事件通知
     86             elif event == select.EPOLLIN:
     87                 recv_data = fd_event_dic[fd].recv(1024).decode("utf-8")
     88                 # 如果有数据
     89                 if recv_data:
     90                     # 调用client_server
     91                     client_server(fd_event_dic[fd], recv_data)
     92                     # 如果是空数据
     93                 else:
     94                     # 调用客户端套接字close()
     95                     fd_event_dic[fd].close()
     96                     # 注销在epoll中的客户端套接字fd
     97                     epl.unregister(fd)
     98                     # 移出字典
     99                     del fd_event_dic[fd]
    100       
    101 
    102     # 关闭套接字
    103     tcp_server_socket.close()
    104 
    105 
    106 if __name__ == '__main__':
    107     main()
  • 相关阅读:
    WPF Image控件的Source属性是一个ImageSource对象
    wx:if 与hidden
    切换远程分支
    异步请求(简单一说)
    多维数组降维方法,简单一提
    3.25发版之最后的搜索框
    wepy-城市按字母排序
    new一个新对象。。。对象???
    参数函数是对象的理解
    群辉 MariaDB 10 远程连接
  • 原文地址:https://www.cnblogs.com/yifengs/p/11422789.html
Copyright © 2011-2022 走看看