【資料整理】Python-簡単なepoll serverコード解読

8956 ワード

Pythonの初心者として、他人のコードを学ぶことも必要です.
Pythonではepollを用いてサービスエンドプログラムを開発する
』のコードで、ソースコードの注釈説明を行います.コードから少なくとも以下の3つの点を学ぶことができます.
  • loggingモジュールの使用;
  • epollの使用;
  • tryの利用方法...catchは「読み書き」を処理します.

  • ======================
    serverエンドコード:
    #!/usr/bin/python
    #-*- coding:utf-8 -*-
    
    import socket, logging
    import select, errno
        
    logger = logging.getLogger("network-server")
        
    def InitLog():
        logger.setLevel(logging.DEBUG)
        
        fh = logging.FileHandler("network-server.log")
        fh.setLevel(logging.DEBUG)
        ch = logging.StreamHandler()
        ch.setLevel(logging.ERROR)
        
        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        ch.setFormatter(formatter)
        fh.setFormatter(formatter)
        
        logger.addHandler(fh)
        logger.addHandler(ch)
            
            
    if __name__ == "__main__":
        InitLog()
    
        try:
            #    TCP socket      socket
            listen_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
        except socket.error, msg:
            logger.error("create socket failed")
    
        try:
            #    SO_REUSEADDR   
            listen_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        except socket.error, msg:
            logger.error("setsocketopt SO_REUSEADDR failed")
    
        try:
            #    bind --       ip   ,  bind       ip  
            listen_fd.bind(('', 2003))
        except socket.error, msg:
            logger.error("bind failed")
    
        try:
            #    listen   backlog  
            listen_fd.listen(10)
        except socket.error, msg:
            logger.error(msg)
        
        try:
            #    epoll   
            epoll_fd = select.epoll()
            #   epoll          socket        
            epoll_fd.register(listen_fd.fileno(), select.EPOLLIN)
        except select.error, msg:
            logger.error(msg)
            
        connections = {}
        addresses = {}
        datalist = {}
        while True:
            # epoll    fd       --              
            epoll_list = epoll_fd.poll()
    
            for fd, events in epoll_list:
                #      fd    
                if fd == listen_fd.fileno():
                    #    accept --        client   ip   port,   socket   
                    conn, addr = listen_fd.accept()
                    logger.debug("accept connection from %s, %d, fd = %d" % (addr[0], addr[1], conn.fileno()))
                    #     socket        
                    conn.setblocking(0)
                    #   epoll          socket        
                    epoll_fd.register(conn.fileno(), select.EPOLLIN | select.EPOLLET)
                    #   conn   addr         
                    connections[conn.fileno()] = conn
                    addresses[conn.fileno()] = addr
                elif select.EPOLLIN & events:
                    #          
                    datas = ''
                    while True:
                        try:
                            #     fd   recv 10     
                            data = connections[fd].recv(10)
                            #           ,            
                            if not data and not datas:
                                #   epoll           fd
                                epoll_fd.unregister(fd)
                                # server           fd
                                connections[fd].close()
                                logger.debug("%s, %d closed" % (addresses[fd][0], addresses[fd][1]))
                                break
                            else:
                                #              datas  
                                datas += data
                        except socket.error, msg:
                            #       socket     recv            
                            #                               
                            if msg.errno == errno.EAGAIN:
                                logger.debug("%s receive %s" % (fd, datas))
                                #           
                                datalist[fd] = datas
                                #    epoll      d         
                                epoll_fd.modify(fd, select.EPOLLET | select.EPOLLOUT)
                                break
                            else:
                                #     
                                epoll_fd.unregister(fd)
                                connections[fd].close()
                                logger.error(msg)
                                break
                elif select.EPOLLHUP & events:
                    #   HUP     
                    epoll_fd.unregister(fd)
                    connections[fd].close()
                    logger.debug("%s, %d closed" % (addresses[fd][0], addresses[fd][1]))
                elif select.EPOLLOUT & events:
                    #          
                    sendLen = 0
                    #    while       buf                   
                    while True:
                        #            client --    sendLen        
                        sendLen += connections[fd].send(datalist[fd][sendLen:])
                        #            while   
                        if sendLen == len(datalist[fd]):
                            break
                    #    epoll       fd         
                    epoll_fd.modify(fd, select.EPOLLIN | select.EPOLLET)
                else:
                    #    epoll        
                    continue

    Clientエンドコード(比較的簡単で、コメントなし):
    import socket
    import time
    import logging
    
    logger = logging.getLogger("network-client")
    logger.setLevel(logging.DEBUG)
    
    fh = logging.FileHandler("network-client.log")
    fh.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)
    
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    
    logger.addHandler(fh)
    logger.addHandler(ch)
    
    if __name__ == "__main__":
        try:
            connFd = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
        except socket.error, msg:
            logger.error(msg)
    
        try:
            connFd.connect(("127.0.0.1", 2003))
            logger.debug("connect to network server success")
        except socket.error,msg:
            logger.error(msg)
    
        for i in range(1, 11):
            data = "The Number is %d" % i
            if connFd.send(data) != len(data):
                logger.error("send data to network server failed")
                break
            readData = connFd.recv(1024)
            print readData
            time.sleep(1)
    
        connFd.close()

    実行結果:
    Clientコマンドライン出力.
    [root@Betty Python]# python epoll_client.py 
    The Number is 1
    The Number is 2
    The Number is 3
    The Number is 4
    The Number is 5
    The Number is 6
    The Number is 7
    The Number is 8
    The Number is 9
    The Number is 10
    [root@Betty Python]#

    Clientログファイル.
    [root@Betty Python]# vi network-client.log 
    
    2013-07-26 15:36:43,995 - network-client - DEBUG - connect to network server success

    serverログファイル.
    [root@Betty Python]# vi network-server.log 
    
    2013-07-26 15:36:43,995 - network-server - DEBUG - accept connection from 127.0.0.1, 34861, fd = 6
    2013-07-26 15:36:43,995 - network-server - DEBUG - 6 receive The Number is 1
    2013-07-26 15:36:44,996 - network-server - DEBUG - 6 receive The Number is 2
    2013-07-26 15:36:45,996 - network-server - DEBUG - 6 receive The Number is 3
    2013-07-26 15:36:46,996 - network-server - DEBUG - 6 receive The Number is 4
    2013-07-26 15:36:47,996 - network-server - DEBUG - 6 receive The Number is 5
    2013-07-26 15:36:48,997 - network-server - DEBUG - 6 receive The Number is 6
    2013-07-26 15:36:49,998 - network-server - DEBUG - 6 receive The Number is 7
    2013-07-26 15:36:50,999 - network-server - DEBUG - 6 receive The Number is 8
    2013-07-26 15:36:52,000 - network-server - DEBUG - 6 receive The Number is 9
    2013-07-26 15:36:53,001 - network-server - DEBUG - 6 receive The Number is 10
    2013-07-26 15:36:54,002 - network-server - DEBUG - 127.0.0.1, 34861 closed

    ======================
    原作者ありがとう!