Python32 Socket Serv

類型

  • socketserver有幾種類型: class socketserver.TCPServer:用於TCP class socketserver.UDPServer:用於UDP class socketserver.UnixStreamServer:用於Unix的TCP class socketserver.UnixDatagramServer:用於Unix的UDP

TCPServer繼承了BaseServer UnixStreamServer繼承了TCPServer

  • 創建socket server至少分以下幾步: 1、必須創建一個請求處理類,並且這個類要繼承BaseRequestHandler,還要重寫父類里的handle方法(跟客戶端所有的交互都是在handle中寫的)。 2、必須要實例化一個協議server(如TCPServer),並且傳遞server ip和你上面創建的請求處理類,給這個TCPServer(實例化的時候將IP和請求處理類傳給TCPServer)。 3、然後可以根據上面的實例來處理請求: server.handle_request() #只處理一個請求 server.handle_forever() #處理多個請求,永遠執行(一般都是用這個) 4、調用server_close()去關閉
server端:    import socketserver    class MyTCPHandler(socketserver.BaseRequestHandler):      '''第1步:創建處理類,繼承Base。 客戶端每一次請求過來都會實例化這個類'''        def handle(self):          '''第1步:重寫handle方法,handle默認存在父類中程式碼是空的。 客戶端所有交互都在handle中完成'''            while True: #使其可以循環發送數據              self.data = self.request.recv(1024).decode().strip()              #這裡的self.request.recv相當於之前用的conn.recv                print ("{} wrote:".format(self.client_address[0]))              #列印客戶端的IP地址資訊                print (self.data)              #列印數據資訊                self.request.send(self.data.upper().encode('utf-8'))              #傳回數據給客戶端,只是upper了一下              #sendall就是重複調用send    if __name__ == "__main__":      HOST,PORT = "localhost",9999        server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)      #第2步:實例化TCPServer,並將IP和MyTCPHandler當做參數傳給請求處理類      #監聽客戶端的每一個請求,就會實例化MyTCPHandler這個類,拿MyTCPHandler的handle與客戶端交互。        server.serve_forever()      #第3步:允許永遠處理多個請求    client端:    import socket    client = socket.socket()  client.connect(('localhost',9999))    while True:        msg = input(">>:").strip()      if len(msg) == 0:continue      client.send(msg.encode('utf-8'))      data = client.recv(1024)      print ("recv:",data.decode())    client.close()    client執行結果:  >>:abc  recv: ABC  >>:efg  recv: EFG  >>:hhh  recv: HHH  >>:    server執行結果:  127.0.0.1 wrote:  abc  127.0.0.1 wrote:  efg  127.0.0.1 wrote:  hhh    client斷開後server報錯:  ----------------------------------------  Exception happened during processing of request from ('127.0.0.1', 53933)  Traceback (most recent call last):    File "D:python37libsocketserver.py", line 313, in _handle_request_noblock      self.process_request(request, client_address)    File "D:python37libsocketserver.py", line 344, in process_request      self.finish_request(request, client_address)    File "D:python37libsocketserver.py", line 357, in finish_request      self.RequestHandlerClass(request, client_address, self)    File "D:python37libsocketserver.py", line 712, in __init__      self.handle()    File "E:/python/程式碼練習/A2.py", line 11, in handle      self.data = self.request.recv(1024).decode().strip()  ConnectionResetError: [WinError 10054] 遠程主機強迫關閉了一個現有的連接。  ----------------------------------------  #可以看到這裡報錯ConnectionResetError: [WinError 10054]
修改server端:  import socketserver    class MyTCPHandler(socketserver.BaseRequestHandler):        def handle(self):            while True: #使其可以循環發送數據             try: #使用try的話就不需要使用 if not data的方式來判斷客戶端斷開時,無數據的情況了                  self.data = self.request.recv(1024).decode().strip()                  #這裡的self.request.recv相當於之前用的conn.recv                    print ("{} wrote:".format(self.client_address[0]))                    print (self.data)                    self.request.send(self.data.upper().encode('utf-8'))             except ConnectionResetError as e:                 print ("err:",e)                 break    #這裡一定要break,不然就會一直死循環    if __name__ == "__main__":      HOST,PORT = "localhost",9999        server = socketserver.TCPServer((HOST,PORT),MyTCPHandler)        server.serve_forever()    server執行結果:  127.0.0.1 wrote:  abc  127.0.0.1 wrote:  123  err: [WinError 10054] 遠程主機強迫關閉了一個現有的連接。  #客戶端斷開連接後,就通過斷言的方式抓到錯誤了。

上面的程式碼目前還不能支援多並發,如果有多個並發,後面的並發就會被掛起; 如果要並發的話,需要修改一下程式碼。

通過ctrl點TCPServer

可以看到TCPServer是繼承了BaseServer

修改server端:    import socketserver    class MyTCPHandler(socketserver.BaseRequestHandler):        def handle(self):            while True: #使其可以循環發送數據             try: #使用try的話就不需要使用 if not data的方式來判斷客戶端斷開時,無數據的情況了                  self.data = self.request.recv(1024).decode().strip()                    print ("{} wrote:".format(self.client_address[0]))                    print (self.data)                    self.request.send(self.data.upper().encode('utf-8'))               except ConnectionResetError as e:                 print ("err:",e)                 break  if __name__ == "__main__":      HOST,PORT = "localhost",9999        server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)      # 上面的程式碼需要使用ThreadingTCPServer        server.serve_forever()    client 1執行結果:  >>:test 1  recv: TEST 1  >>:    client 2執行結果:  >>:test 2  recv: TEST 2  >>:    client 3執行結果:  >>:test 3  recv: TEST 3  >>:    server 執行結果:  127.0.0.1 wrote:  test 1  127.0.0.1 wrote:  test 2  127.0.0.1 wrote:  test 3

可以看到server端現在支援多並發,沒有被掛起;每來一個請求會開啟一個新執行緒與server交互;每個執行緒都是獨立的,10個執行緒,就可以做10件事情。

通過ctrl點ThreadingTCPServer

可以看到將TCPServer這個類傳了進去 同時還傳了ThreadingMixIn;TCPServer是負責與客戶端交互,而多執行緒都是由ThreadingMixIn實現的。

ctrl點ThreadingMixIn

這部分就是多執行緒的主要程式碼