SocketServer源碼學習(二)

SocketServer 中很是重要的兩個基類就是:BaseServer 和 BaseRequestHandler
在SocketServer 中也提供了對TCP以及UDP的高級封裝,此次咱們主要經過分析關於TCP的處理邏輯來對SocketServer模塊進行一個很好的理解和學習緩存

TCPServer

TCPServer 繼承了BaseServer,初始化的時候,進行了socket套接字的建立。網絡

def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
    """Constructor.  May be extended, do not override."""
    BaseServer.__init__(self, server_address, RequestHandlerClass)
    self.socket = socket.socket(self.address_family,
                                self.socket_type)
    if bind_and_activate:
        try:
            self.server_bind()
            self.server_activate()
        except:
            self.server_close()
            raise

在這裏咱們看到了咱們很是熟悉的關於socket的建立的內容:
self.socket = socket.socket(self.address_family, self.socket_type)
經過socket模塊建立了socket對象,接着調用了server_bind和server_activatesocket

server_bind

源碼內容以下:tcp

def server_bind(self):
    """Called by constructor to bind the socket.

    May be overridden.

    """
    if self.allow_reuse_address:
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    self.socket.bind(self.server_address)
    self.server_address = self.socket.getsockname()

這裏咱們看到了很是熟悉的操做socket.bind方法,以及設置了socket的相關屬性ide

server_activate

源碼內容以下:函數

def server_activate(self):
    """Called by constructor to activate the server.

    May be overridden.

    """
    self.socket.listen(self.request_queue_size)

一樣的這裏的調用也很是簡單就是執行了socket.listen學習

get_request

在TCPServer類中咱們還看到了get_request方法,源碼內容以下:this

def get_request(self):
    """Get the request and client address from the socket.

    May be overridden.

    """
    return self.socket.accept()

這個的調用其實咱們能夠在BaseServer這個基類中看到,咱們以前看過關於BaseServer中這個基類的源碼
咱們能夠從咱們調用BaseServer基類中的serve_forever方法查看,這裏是調用了_handle_request_noblock方法,我繼續查看_handle_request_noblock這個源碼spa

def _handle_request_noblock(self):
    """Handle one request, without blocking.

    I assume that selector.select() has returned that the socket is
    readable before this function was called, so there should be no risk of
    blocking in get_request().
    """
    try:
        request, client_address = self.get_request()
    except OSError:
        return
    if self.verify_request(request, client_address):
        try:
            self.process_request(request, client_address)
        except:
            self.handle_error(request, client_address)
            self.shutdown_request(request)
    else:
        self.shutdown_request(request)

能夠看到這裏最後是調用了process_request來處理請求,繼續查看源碼:code

def process_request(self, request, client_address):
    """Call finish_request.

    Overridden by ForkingMixIn and ThreadingMixIn.

    """
    self.finish_request(request, client_address)
    self.shutdown_request(request)

def finish_request(self, request, client_address):
    """Finish one request by instantiating RequestHandlerClass."""
    self.RequestHandlerClass(request, client_address, self)

從上面的代碼咱們能夠到最後是在finish_request中實例化了RequestHandlerClass
咱們 這個時候查看一下BaseRequestHandler這個基類的源碼以下:

class BaseRequestHandler:

    """Base class for request handler classes.

    This class is instantiated for each request to be handled.  The
    constructor sets the instance variables request, client_address
    and server, and then calls the handle() method.  To implement a
    specific service, all you need to do is to derive a class which
    defines a handle() method.

    The handle() method can find the request as self.request, the
    client address as self.client_address, and the server (in case it
    needs access to per-server information) as self.server.  Since a
    separate instance is created for each request, the handle() method
    can define other arbitrary instance variables.

    """

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

在初始化函數裏咱們看到了調用setup()方法,這setup在StreamRequestHandler會被重寫

StreamRequestHandler

TCPServer實現了使用tcp套接字的網絡服務,Handler方面則是對應的StreamRequestHandler。它繼承了BaseRequestHandler。基類的setup方法和finish方法被它重寫,用於經過鏈接實現緩存文件的讀寫操做。

setup方法

源碼內容以下:

def setup(self):
    self.connection = self.request
    if self.timeout is not None:
        self.connection.settimeout(self.timeout)
    if self.disable_nagle_algorithm:
        self.connection.setsockopt(socket.IPPROTO_TCP,
                                   socket.TCP_NODELAY, True)
    self.rfile = self.connection.makefile('rb', self.rbufsize)
    self.wfile = self.connection.makefile('wb', self.wbufsize)

這裏主要設置了對應鏈接的屬性,其中建立了兩個對象很是重要:
一個可讀(rfile)和一個可寫(wfile)的「文件」對象
可是實際並非建立了文件,而是封裝了讀取數據和發送數據的操做,抽象成了對文件的操做
能夠理解:
self.rfile 就是讀取客戶端數據的對象,它有一些方法能夠讀取數據。self.wfile則是用來發送數據給客戶端的對象。

整理流程(TCP)

實現TCP服務須要使用TCPServer和StreamRequestHandler共同協做

相關文章
相關標籤/搜索