python: 玩玩EPOLL

2019-11-22 09:32:45 浏览数 (2)

玩一会epoll,果然好玩

代码语言:javascript复制
import select

import socket
import time


def svc():
    EOL1 = b'nn'
    EOL2 = b'nrn'
    response = b'HTTP/1.0 200 OKrnDate: Mon, 1 Jan 1996 01:01:01 GMTrn'
    response  = b'Content-Type: text/plainrnContent-Length: 13rnrn'
    response  = b'Hello, world!'

    # 创建套接字对象并绑定监听端口
    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)

    # 创建epoll对象,并注册socket对象的 epoll可读事件
    epoll = select.epoll()
    epoll.register(serversocket.fileno(), select.EPOLLIN|select.EPOLLET)

    try:
        connections = {}
        requests = {}
        responses = {}
        while True:
            time.sleep(0.1)
            # 主循环,epoll的系统调用,一旦有网络IO事件发生,poll调用返回。这是和select系统调用的关键区别
            events = epoll.poll(1)
            # 通过事件通知获得监听的文件描述符,进而处理
            for fileno, event in events:
                print("event {}".format(event))
                # 注册监听的socket对象可读,获取连接,并注册连接的可读事件
                if fileno == serversocket.fileno():
                    print("start accept fileno {}".format(fileno))
                    connection, address = serversocket.accept()
                    connection.setblocking(0)
                    epoll.register(connection.fileno(), select.EPOLLIN|select.EPOLLET)
                    connections[connection.fileno()] = connection
                    requests[connection.fileno()] = b''
                    responses[connection.fileno()] = response
                elif event & select.EPOLLIN:
                    # 连接对象可读,处理客户端发生的信息,并注册连接对象可写
                    msg = connections[fileno].recv(1)
                    print("fileno {}, rec: {}".format(fileno, msg))
                    requests[fileno]  = msg
                    if msg == b'':
                        epoll.modify(fileno, 0)
                        connections[fileno].shutdown(socket.SHUT_RDWR)

                    if EOL1 in requests[fileno] or EOL2 in requests[fileno]:
                        epoll.modify(fileno, select.EPOLLOUT)
                        print('-' * 40   'n'   requests[fileno].decode()[:-2])
                elif event & select.EPOLLOUT:
                    print("select.EPOLLOUT start")
                    # 连接对象可写事件发生,发送数据到客户端
                    byteswritten = connections[fileno].send(responses[fileno])
                    responses[fileno] = responses[fileno][byteswritten:]
                    if len(responses[fileno]) == 0:
                        epoll.modify(fileno, 0)
                        connections[fileno].shutdown(socket.SHUT_RDWR)
                elif event & select.EPOLLHUP or event & (select.EPOLLIN
                                                             | select.EPOLLRDHUP):
                    print("select.EPOLLHUP start")
                    epoll.unregister(fileno)
                    connections[fileno].close()
                    del connections[fileno]
    finally:
        epoll.unregister(serversocket.fileno())
        epoll.close()
        serversocket.close()
        serversocket.close()


def cli():
    host = "localhost"
    port = 8164
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    try:
        while 1:
            msg = input()
            if msg == 'close':
                s.close()
                return
            s.send(msg.encode())

            # print(s.recv(1024))
    finally:
        s.close()


# svc()
# cli()
import sys

print(sys.argv)
if sys.argv[1] == 'cli':
    cli()
else:
    svc()

0 人点赞