Python Web服务器 (epoll版的服务器)

  1. 用 epl = select.epoll   # 来创建epoll对象
  2. epl.register(xxx.fileno(),select.EPOLLIN)  # 将监听套接字对应的fd注册到epoll 中  fd_event_list = epl.poll   (返回的是一个列表)
    # 默认会堵塞,直到os检测到有数据到来,通过事件通知方式告诉这个程序,此时次啊会解堵塞。这样就不会在没有数据的时候一直循环执行浪费资源
    1. xx.fileno 代表套接字的fd 即套接字对应的文件描述符
    2. 设定套接字有数据进来时候通知
  3. fd_event_list = [(fd,event),(就是套接字的对应文件描述符,和这个描述符的事件)]
  4. 使用 xxx.fileno 可以得到套接字的文件描述符,到有文件描述符不能直接得到套接字,所以可以用到字典把两样东西结合起来
import socket
import re
import time
import select

def service_client(client_socket,recv_data):
    
    # recv/send接受发送数据额
    recv_list =recv_data.splitlines()
    req = re.search(r"/[^ ]*",recv_list[0]).group()
    if req:
        if req == '/':
            req = '/index.html'
    print(req)
    try:
        with open('D:\python\jichuu\Web服务器\moban897'+req,'rb') as f:
            response_body = f.read()
    except :
        response_header ="HTTP/1.1 404 NOT FOUND\n\r\n"
        response_body = '<h1>nonono</h1>'
        response_body = response_body.encode('utf-8')
        
    else:
        response_header ="HTTP/1.1 200 OK\n"
        response_header += "Content-Length:%d\n\r\n" %(len(response_body))

    response_header = response_header.encode('utf-8')
    response = response_header + response_body
    client_socket.send(response)
    client_socket.close()
    
def main():
    # socket创建一个套接字
    tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    tcp_server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  
    # 一定要绑定IP和端口,就跟110一样,是固定的让人随时能知道
    tcp_server.bind(('192.168.124.32',7890))
    # listen使套接字变成可以被动链接
    tcp_server.listen(128)
    tcp_server.setblocking(False) # 将套接字变为非堵塞
    
    epl = select.epoll()  # 创建eoll对象
    # 将监听套接字对应的fd注册到epoll 中 
    epl.register(tcp_server.fileno(),select.EPOLLIN)
    epl_dict = dict()
    
    # 循环为多个客户端服务
    while True:
        # 默认会堵塞,直到os检测到有数据到来,通过事件通知方式告诉这个程序
        # 此时次啊会解堵塞。这样就不会在没有数据的时候一直循环执行浪费资源
        fd_event_list = epl.poll
        for fd,event in fd_event_list:
            if fd == tcp_server.fileno():
                new_socket,client_add = tcp_server.accept()
                epl.register(new_socket.fileno(),select.EPOLLIN)
                epl_dict[new_socket.fileno()] = new_socket
            elif event == select.EPOLLIN:
                recv_data = epl_dict[fd].recv(1024).decode("utf-8")
                if recv_data:
                    service_client(epl_dict[fd],recv_data)
                else:
                    epl_dict[fd].close()
                    epl.unregister(fd)
                    del epl_dict[fd]

                
    tcp_server.close()
    
if __name__ == '__main__':
    main()

 

posted @ 2020-03-05 15:37  otome  阅读(296)  评论(0编辑  收藏  举报