美文网首页网络编程魔法Tornado
Python SocketServer.py 源码分析(三)

Python SocketServer.py 源码分析(三)

作者: 人世间 | 来源:发表于2015-05-30 15:28 被阅读681次

前面我们见识了实现TCPServer的方法。最早关于介绍BaseServer的时候,我们知道python对BaseServer设计的时候,预留了可用于Mixin扩展多线程或多进程的接口。mixin通过复写父类的parse_request方法实现。

ThreadingMixIn

ThreadingMixIn 类实现了多线程的方式,它只有两个方法,分别是process_request和 process_request_thread方法。多进程的方式是ForkingMixIn,暂且略过。

process_request

def process_request(self, request, client_address):
    t = threading.Thread(target = self.process_request_thread,
                         args = (request, client_address))
    t.daemon = self.daemon_threads
    t.start()

process_request方法复写了父类的此方法。以此为接口入口,对每一个请求,调用Thread开启一个新的线程。每一个线程都绑定process_request_thread方法。

process_request_thread

    def process_request_thread(self, request, client_address):
        try:
            self.finish_request(request, client_address)
            self.shutdown_request(request)
        except:
            self.handle_error(request, client_address)
            self.shutdown_request(request)

process_request_thread方法和BaseServer里的parse_request几乎一样。只不过是多线程的方式调用。

使用的时候,通过多继承调用接口,例如:

class ThreadingTCPServer(ThreadingMixIn, TCPServer): 
    pass

具体的调用过程如下:


ThreadingMixIn -- TCPServer - StreamRequestHandler

__init__(server_address, RequestHandlerClass): 
    BaseServer.server_address
    BaseServer.RequestHandlerClass

    TCPServer.socket = socket.socket(self.address_family, self.socket_type)
    TCPServer.server_bind()
    TCPServer.server_activate()

serve_forever(): 

    select() 

    BaseServer._handle_request_noblock()

        TCPServer.get_request() -> request, client_addres
            socket.accept()

        BaseServer.verify_request()

            BaseServer.process_request()

                ThreadingMixIn.process_request()
                    t = threading.Thread(target = ThreadingMixIn.process_request_thread)

                    ThreadingMixIn.process_request_thread

                        BaseServer.finish_request(request, client_address)

                            BaseServer.RequestHandlerClass()

                                BaseRequestHandler.__init__(request)

                                    BaseRequestHandler.request
                                    BaseRequestHandler.client_address = client_address

                                    StreamRequestHandler.setup()

                                        StreamRequestHandler.connection = StreamRequestHandler.request
                                        StreamRequestHandler.rfile
                                        StreamRequestHandler.wfile

                                    BaseRequestHandler.handle()

                                    StreamRequestHandler.finsih()
                                        StreamRequestHandler.wfile.close()
                                        StreamRequestHandler.rfile.close()

                        BaseServer.shutdown_request(request)
                            TCPServer.shutdown()
                                request.shutdown()
                            TCPServer.close_request(request)
                                request.close()

            TCPServer.shutdown_request(request)
                TCPServer.shutdown(request)
                    request.shutdown()
                TCPServer.close_request(request)
                    request.close()

相关文章

网友评论

  • 胸毛飘荡:大神,我又来了,想请问一下,如果想在web中实现会话(即时通讯)聊天功能,同时保证上万的用户进行一对一,一对多,多对多的即时消息传递。应该使用SocketServer还是flask-socketio? 项目使用的是flask框架,大神可否提供一下思路?
    人世间:@7sunshine_45b6 如果是使用tornado的websocket,服务端始终是一个线程处理。只不过每一个websocket开启一个tcp连接。单机cover上万连接也就是C10k的数量级。短连接肯定没问题,websocket长连接的上限我也不是很清楚。您可以开部分流量来测试开发。据说golang和elixir 单机百万长连接很轻松。
    胸毛飘荡:@人世间 以前我用Java也做过,记得是一个用户分配一个线程,当有几万用户同时在线的话,那就有几万个线程,服务器是否能撑住?大神有试过吗?当初我只是写了demo随便玩玩,也就同时在线几个客户端。
    人世间:聊天一般都是使用长连接协议。web中可以用 websocket,flask-socketio支持websocket,没用过不了解。tornado中也实现了websocket,官网的demo https://github.com/tornadoweb/tornado/tree/master/demos/chat

本文标题:Python SocketServer.py 源码分析(三)

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