zoukankan      html  css  js  c++  java
  • Web服务器-并发服务器-Epoll(3.4.5)

    @

    1.介绍

    epoll是一种解决方案,nginx就是用的这个
    中心思想:不要再使用多进程,多线程了,使用单进程,单线程去实现并发
    在上面博客实现的代码中使用过的轮询去查看套接字有没有数据,而epoll是主动通知
    当使用多进程的时候,是复制一份资源去查看,epoll不用复制,直接来
    优势:1.共享内存 2.事件通知

    2.代码

    import socket
    import select
    
    
    def tcp_server(new_tcp_socket, request):
    
        request_lines = request.splitlines()
        print(request_lines)
        print(">" * 30)
        try:
            file = open("./test/login.html", "rb")
        except:
        	# 构造响应头
            response_header = "HTTP/1.1 404 NOT FOUND
    "
            response_header += "
    "
            response_header += "----file not found-----"
            new_tcp_socket.send(response_header.encode("utf-8"))
        else:
            html_content = file.read()
            file.close()
            response_body = html_content
            response_header = "HTTP/1.1 200 OK
    "
            # 使用Content-Length实现长连接
            response_header += "Content-Length:%d
    " % len(response_body)
            response_header += "
    "
            response = response_header.encode("utf-8") + response_body
            # 发送响应数据
            new_tcp_socket.send(response)
    
    
    def main():
        """对大致流程进行控制"""
        # 1.创建tcp套接字
        tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置当服务器先close()即服务器4次挥手之后资源立即释放
        tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 2.绑定端口
        tcp_socket.bind(("", 7890))
        # 3.监听套接字
        tcp_socket.listen(128)
        tcp_socket.setblocking(False)
        # 创建一个epoll对象
        epoll = select.epoll()
        # 将监听套接字对应的fd注册到epoll中,并绑定事件   fd:文件描述符
        epoll.register(tcp_socket.fileno(), select.EPOLLIN)
        # 定义保存socket的字典
        fd_event_dict = dict()
        while True:
            # 默认堵塞,直到OS检测到数据到来通过事件通知方式告诉程序,才会解堵塞 返回list
            fd_event_list = epoll.poll()
            # [(fd,event)] (套接字对应的文件描述符,这个文件描述符对应的到底是什么事件,例如可以调用recv接收等)
    
            # 遍历元组
            for fd, event in fd_event_list:
                if fd == tcp_socket.fileno():
                    new_tcp_socket, client_addr = tcp_socket.accept()
                    epoll.register(new_tcp_socket.fileno(), select.EPOLLIN)
                    # 通过字典保存socket,键为fd,值为socket
                    fd_event_dict[new_tcp_socket.fileno()] = new_tcp_socket
                elif event == select.EPOLLIN:
                    # 判断已经链接的客户端是否有数据发送过来
                    recv_data = fd_event_dict[fd].recv(1024).decode("utf-8")
                    if recv_data:
                        # 有数据操作
                        # 4.为这个客户端服务
                        tcp_server(fd_event_dict[fd], recv_data)
                    else:
                        # 无数据操作
                        fd_event_dict[fd].close()
                        epoll.unregister(fd)
                        del fd_event_dict[fd]
        # 关闭监听套接字
        tcp_socket.close()
    
    
    if __name__ == '__main__':
        main()
    
    

    关于作者

    个人博客网站
    个人GitHub地址
    个人公众号:
    在这里插入图片描述

  • 相关阅读:
    (转) c++ 迭代器
    (转) 学习C++ -> 向量(vector)
    latex 模版
    javascript继承篇
    ES6的Map和Set的使用,以及weakMap的一点理解
    JavaScript中的eval函数
    Node.js中的进程与线程
    普通函数与箭头函数的区别是什么?
    git 远程拉去代码 输入用户名密码
    npm 设置镜像
  • 原文地址:https://www.cnblogs.com/simon-idea/p/11399900.html
Copyright © 2011-2022 走看看