美文网首页
python epoll tcp server

python epoll tcp server

作者: help_youself | 来源:发表于2021-01-26 20:28 被阅读0次

    tcp_epoll_server.py

    #https://www.jianshu.com/p/cdfddb026db0
    #https://github.com/fschr/simpletcp/blob/master/simpletcp/serversocket.py
    #https://stackoverflow.com/questions/16745409/what-does-pythons-socket-recv-return-for-non-blocking-sockets-if-no-data-is-r
    #http://scotdoyle.com/python-epoll-howto.html
    import signal, os
    import threading
    import socket
    import select
    import errno
    SERVER_ERR_INVAL=-1
    class TcpServer:
        def __init__(self, mode, port,callback):
            self._thread = None
            self._thread_terminate = False
            # localhost -> (127.0.0.1)
            # public ->    (0.0.0.0)
            # otherwise, mode is interpreted as an IP address.
            if mode == "localhost":
                self.ip = mode
            elif mode == "public":
                self.ip ="0.0.0.0"
            else:
                self.ip ="127.0.0.1"
            self.port = port
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self._socket.setblocking(False)
            self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self._socket.bind((self.ip, self.port))
            self.connections={}
            self.callback =callback
            self._socket.listen(128)
            self._epl= select.epoll()
            self._epl.register(self._socket.fileno(),select.EPOLLIN)
        def loop_start(self):
            if self._thread is not None:
                return 
            self._thread_terminate = False
            self._thread = threading.Thread(target=self._thread_main)
            #self._thread.daemon = True
            self._thread.start()
        def loop_stop(self, force=False):
            if self._thread is None:
                return SERVER_ERR_INVAL
            self._thread_terminate = True
            if threading.current_thread() != self._thread:
                self._thread.join()
                self._thread = None
        def loop_once(self):
            epoll_list = self._epl.poll(0)
            for fd,events in epoll_list:
                if fd == self._socket.fileno():
                    conn,addr =self._socket.accept()
                    conn.setblocking(False)
                    self.connections.update({conn.fileno():conn})
                    self._epl.register(conn.fileno(), select.EPOLLIN)
                elif events == select.EPOLLIN:
                    print("in event")
                    buffer=b""
                    count=0
                    try:
                        while True:
                            msg= self.connections[fd].recv(1500)
                            count+=1
                            if msg:
                                buffer+=msg
                            else:
                                if buffer:
                                    self.callback(self.connections[fd],buffer)
                                    buffer=b""
                                self._epl.unregister(fd)
                                self.connections[fd].close()
                                self.connections.pop(fd)
                                break
                    except socket.error as e:
                        err = e.args[0]
                        print (err,count)
                        if buffer:
                            ret=self.callback(self.connections[fd],buffer)
                            if ret:
                                self._close(fd)
                        if err == errno.EAGAIN or err == errno.EWOULDBLOCK:
                            pass
                        else:
                            self._close(fd)
        def _thread_main(self):
            while True:
                if self._thread_terminate is True:
                    break
                self.loop_once(retry_first_connection=True)
        def _close(self,fd):
            if fd==self._socket.fileno():
                self._epl.unregister(fd)
                self._socket.close()
            elif fd in self.connections:
                self._epl.unregister(fd)
                self.connections[fd].close()
                self.connections.pop(fd)
        def shut_down(self):
            for fd, conn in self.connections.items():
                self._epl.unregister(fd)
                conn.close()
            self.connections.clear()
            self._close(self._socket.fileno())
    def echo_back(conn,buffer):
        print(buffer.decode('utf-8'))
        conn.sendall(buffer)
        return True
    Terminate=False
    def signal_handler(signum, frame):
        global Terminate
        Terminate =True
    
    #netstat -tunlp | grep port
    if __name__ == '__main__':
        signal.signal(signal.SIGTERM, signal_handler)
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGHUP, signal_handler) # ctrl+c
        signal.signal(signal.SIGTSTP, signal_handler) #ctrl+z
        echo_server=TcpServer("localhost",3345,echo_back)
        while True:
            echo_server.loop_once()
            if Terminate:
                echo_server.shut_down()
                break
    print("stop")
    

    The client I use during test, tcp_client.py.

    #https://blog.csdn.net/jerryhanjj/article/details/69047515
    import socket
    if __name__ == '__main__':
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect(('localhost', 3345))
        sendbuf ="hello world,dididdidididididididididddididdidi"                  
        client.send(sendbuf.encode('utf-8'))   
        recvbuf = client.recv(1024)
        print(recvbuf.decode('utf-8'))
        client.close()  
        print('Connection was closed...')
    

    Reference:
    [1] How To Use Linux epoll with Python
    [2] python socket编程 tcp 简单示例

    相关文章

      网友评论

          本文标题:python epoll tcp server

          本文链接:https://www.haomeiwen.com/subject/mjjnzktx.html