socketserver模塊解析


  • socketserver模塊是基於socket而來的模塊,它是在socket的基礎上進行了一層封裝,並且實現並發等功能。

  •  

    • 看看具體用法:

       
       
       
      x
       
       
       
       
      import socketserver                              #1、引入模塊
      class MyServer(socketserver.BaseRequestHandler): #2、自己寫一個類,類名自己隨便定義,然后繼承socketserver這個模塊里面的BaseRequestHandler這個類
          def handle(self):              #3、寫一個handle方法,必須叫這個名字,不寫運行父類的pass
              #self.request             #6、self.request 相當於一個conn
              self.request.recv(1024)                  #7、收消息
              msg = '親,學會了嗎'
              self.request.send(bytes(msg,encoding='utf-8')) #8、發消息
              self.request.close()                     #9、關閉連接
           # 拿到了我們對每個客戶端的管道,那么我們自己在這個方法里面的就寫我們接收消息發送消息的邏輯就可以了
              pass
      if __name__ == '__mian__':
          #thread 線程,現在只需要簡單理解線程,別着急,后面很快就會講到啦,看下面的圖
          server = socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer)#4、使用socketserver的ThreadingTCPServer這個類,將IP和端口的元祖傳進去,還需要將上面咱們自己定義的類傳進去,得到一個對象,相當於我們通過它進行了bind、listen
          server.serve_forever()                       #5、使用我們上面這個類的對象來執行serve_forever()方法,他的作用就是說,我的服務一直開啟着,就像京東一樣,不能關閉網站,對吧,並且serve_forever()幫我們進行了accept
      #注意:
      #有socketserver 那么有socketclient的嗎?
      #當然不會有,我要作為客戶去訪問京東的時候,京東幫我也客戶端了嗎,客戶端是不是在我們自己的電腦啊,並且socketserver對客戶端沒有太高的要求,只需要自己寫一些socket就行了
       
    • 簡單的應用

       
       
       
      xxxxxxxxxx
       
       
       
       
      #服務端
      import socketserver
      class Myserver(socketserver.BaseRequestHandler):
          def handle(self):
              self.data = self.request.recv(1024).strip()
              print("{} wrote:".format(self.client_address[0]))
              print(self.data)
              self.request.sendall(self.data.upper())
      if __name__ == "__main__":
          HOST, PORT = "127.0.0.1", 9999
          # 設置allow_reuse_address允許服務器重用地址
          socketserver.TCPServer.allow_reuse_address = True
          # 創建一個server, 將服務地址綁定到127.0.0.1:9999
          #server = socketserver.TCPServer((HOST, PORT),Myserver)
          server = socketserver.ThreadingTCPServer((HOST, PORT),Myserver)
          # 讓server永遠運行下去,除非強制停止程序
          server.serve_forever()
          
      #客服端
      import socket
      HOST, PORT = "127.0.0.1", 9999
      data = "hello"
      # 創建一個socket鏈接,SOCK_STREAM代表使用TCP協議
      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
          sock.connect((HOST, PORT))          # 鏈接到客戶端
          sock.sendall(bytes(data + "\n", "utf-8")) # 向服務端發送數據
          received = str(sock.recv(1024), "utf-8")# 從服務端接收數據
      print("Sent:     {}".format(data))
      print("Received: {}".format(received))
       

       

  • socketserver模塊源碼解讀

    img

    • 從上圖我們可以看出SocketServer主要被抽象為兩個主要的類: BaseServer類,用於處理連接相關的網絡操作 BaseRequestHandler類,用於實際處理數據相關的操作,SocketServer還提供了兩個MixIn類:ThreadingMinxIn和ForkingMixinl 用於擴展server,實現多進程和多線程。

       
       
       
      xxxxxxxxxx
       
       
       
       
      #以下從這幾個主要的類開始做整體分析
      #BaseServer類:
         # server_activate
         # serve_forever
         # shutdown
         # service_actions
         # handle_request
         # handlerequest_noblock
         # handle_timeout
         # verify_request
         # process_request
         # server_close
         # finish_request
         # shutdown_request
         # close_request
         # handle_error
      #先看看BaseServer的初始化函數,主要是實現創建server對象,並初始化serve地址和處理請求的類:RequestHandlerClass
      def __init__(self, server_address, RequestHandlerClass):
          """Constructor. May be extended, do not override."""
          self.server_address = server_address
          self.RequestHandlerClass = RequestHandlerClass
          self.__is_shut_down = threading.Event()
          self.__shutdown_request = False
          
      #serve_forever函數,創建server對象之后我們會使用server對象開啟無限循環,接受一個參數poll_interval,用於表示select輪詢的時間,然后進入一個死循環,用select方法進行網絡IO的監聽,這里通過調用selector.register(self, selectors.EVENT_READ)進行了注冊,當ready有返回是,表示有IO連接或者數據,這個時候會調用_handle_request_noblock
      def serve_forever(self, poll_interval=0.5): 
          self.__is_shut_down.clear()
          try:
              with _ServerSelector() as selector:
                  selector.register(self, selectors.EVENT_READ) #檢測是否注冊
                  while not self.__shutdown_request:
                      ready = selector.select(poll_interval) # 監聽
                      if ready:
                          self._handle_request_noblock()
                      self.service_actions()
          finally:
              self.__shutdown_request = False
              self.__is_shut_down.set()
              
      #handlerequest_noblock函數,即開始處理一個請求,並且是非阻塞。該方法通過get_request方法獲取連接,具體的實現在其子類。一旦得到了連接,調用verify_request方法驗證請求。驗證通過,即調用process_request處理請求。如果中途出現錯誤,則調用handle_error處理錯誤,以及shutdown_request結束連接,而verify_request中默認直接返回True,所以當驗證通過后講調用process_request
      def _handle_request_noblock(self):
          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函數, process_request方法是mixin的入口,MixIn子類通過重寫該方法,進行多線程或多進程的配置 。調用finish_request完成請求的處理,同時調用shutdown_request結束請求.
      def process_request(self, request, client_address):
          self.finish_request(request, client_address)
          self.shutdown_request(request)
          
       #finish_request函數,關於請求的部分到這里就已經處理完畢,接下來是要對數據的處理,finish_request方法將會處理完畢請求.
      #BaseRequestHandler類,用於實際處理數據相關的操作.
      #初始化函數,該類會處理每一個請求。初始化對象的時候,設置請求request對象。然后調用setup方法,子類會重寫該方法,用於處理socket連接。接下來的將是handler和finish方法。所有對請求的處理,都可以重寫handler方法。
      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()
       
                         
       

       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM