zoukankan      html  css  js  c++  java
  • python之epoll服务器源码分析

    #!/usr/bin/env python
    # -*- coding: utf8 -*-
    
    import socket, select
    
    EOL1 = b'/r/n'
    EOL2 = b'/r/n/r/n'
    
    # 拼接成的response
    response = b'HTTP/1.0 200 OK/r/nDate: Mon, 1 Jan 1996 01:01:01 GMT/r/n'
    response += b'Content-Type: text/plain/r/nContent-Length: 13/r/n/r/n'
    response += b'Hello, world!'
    
    # 创建一个服务端的socket,来监听是否有请求过来
    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serversocket.bind(('0.0.0.0', 8080))  # 绑定
    serversocket.listen(1)  # 监听
    serversocket.setblocking(0)  # 设置时非阻塞
    print(serversocket.fileno())
    epoll = select.epoll()  # 准备设计一个IO多路复用
    epoll.register(serversocket.fileno(), select.EPOLLIN)  # 把上面的serversocket的fileno() 和 监听准备读信号 注册到epoll中去
    
    try:
        # 设置三个空字典
        connections = {}
        requests = {}
        responses = {}
        while True:
            # 查看epoll是否有信号有的话,就放在events中
            events = epoll.poll(1)
    
            # 循环events,分别拿到 文件描述号 和对应的事件
            for fileno, event in events:
                # 如果当前的文件描述号是serversocket,那么说明有新的连接
                if fileno == serversocket.fileno():
                    # 所以就得接受,创建了 连接,拿到了对方的IP地址
                    connection, address = serversocket.accept()
                    # connection就是客户端连接过来建立的socket,设置为非阻塞
                    connection.setblocking(0)
                    # 客户端建立的socket也注册到select模块的IO多路复用中去
                    epoll.register(connection.fileno(), select.EPOLLIN)
    
                    # 以Connection的文件描述号 作为键 socket作为值保存在connections中
                    connections[connection.fileno()] = connection
    
                    # 同时在requests和responses字典中,
                    # requests中 以connection.fileno() 作为键 以请求的内容作为值
                    # responses中 以connection.fileno() 作为键 以相应的内容作为值,这个我们返回的是固定的,仅仅返回hello world
    
                    requests[connection.fileno()] = b''
                    responses[connection.fileno()] = response
    
                # 如果请求的数据不是socketserver,那肯定是客户端的,判断是否是准备读的信号
                elif event & select.EPOLLIN:
                    # 立马来开始读取数据,加到requests对象套接字的内容中去
                    requests[fileno] += connections[fileno].recv(1024)
    
                    # 判断换行 和 两个换行是否在接收过来的数据中
                    if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
                        # 如果是的话,就将这个套接字的监听更新为准备写
                        epoll.modify(fileno, select.EPOLLOUT)
    
                        # 打印40个-,然后换行,加上请求的内容
                        print('-' * 40 + '/n' + requests[fileno].decode()[:-2])
                # 如果请求的数据不是socketserver,那肯定是客户端的,判断是否是准备写的信号
                elif event & select.EPOLLOUT:
                    # 立马来开始读取数据,就将response的对应的套接字号对应的值拿出来,其实就是hello world,O(∩_∩)O哈哈~
                    # 并统计发送了多少个字节
                    byteswritten = connections[fileno].send(responses[fileno])
                    # 更新response对应套接字内容为剩下的内容
                    responses[fileno] = responses[fileno][byteswritten:]
                    # 如果内容发完了,剩下的长度就是0,如果长度是0
                    if len(responses[fileno]) == 0:
                        # 就修改select,不监听该套接字的内容,其就变成了EPOLLHUP
                        epoll.modify(fileno, 0)
                        # 然后关闭该socket的管道
                        connections[fileno].shutdown(socket.SHUT_RDWR)
                elif event & select.EPOLLHUP:
                    # 如果不监听该套接字的内容,就将其注销掉
                    epoll.unregister(fileno)
                    # 关闭该套接字
                    connections[fileno].close()
                    # 从连接中删除该文件描述符
                    del connections[fileno]
    finally:
        # 最后关闭serversocket服务器套接字
        epoll.unregister(serversocket.fileno())
        # 关闭epoll
        epoll.close()
        # 套接字关闭
        serversocket.close()
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/nulige/p/6880621.html
Copyright © 2011-2022 走看看