SocketServer簡化了網絡服務器的編寫。在進行socket建立時,使用SocketServer會大大減小建立的步驟,而且SocketServer使用了select它有5個類:BaseServer,TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。後4個類是同步進行處理的,另外經過ForkingMixIn和ThreadingMixIn類來支持異步。python
SocketServer的5個類的繼承關係服務器
SocketServer內部使用 IO多路複用 以及 「多線程」 和 「多進程」 ,從而實現併發處理多個客戶端請求的Socket服務端。即:每一個客戶端請求鏈接到服務器時,Socket服務端都會在服務器是建立一個「線程」或者「進 程」 專門負責處理當前客戶端的全部請求。網絡
一是Server類:BaseServer/TCPServer/UDPServer用來接收客戶的請求。TCPServer處理TCP請求,UDPServer處理UDP請求。BaserServer是基類,不能直接使用。TCPServer繼承自BaseServer,UDPServer繼承自TCPServer。多線程
二是Handler類:BaseRequestHandler/DatagramRequestHandler/StreamRequestHandler用來處理每個客戶請求。通常用使用BaseRequestHandler就行,但StreamRequestHandler/DatagramRequestHandler提供了一些特別的功能,前者用來處理流式(TCP)請求,後者處理數據報(UDP)請求。Server每收到一個客戶請求就會建立一個Handler類示例來處理該請求。默認狀況下,TCPServer/UDPServer是單進程單線程的模型,依次處理每一個客戶請求,一個請求處理完畢才能接着處理下一個請求。併發
三是MixIn類:ForkingMixIn/ThreadingMixIn用來爲Server提供多進程/多線程併發處理能力的。ForkingMixIn是多進程模型,ThreadingMixin是多線程模型。這裏特別巧妙的是,你只要建立一個類,同時繼承Server類和MixIn類就能自動得到併發處理請求的能力。該模塊自己就直接提供了這種類。異步
class ForkingUDPServer(ForkingMixIn, UDPServer): pass class ForkingTCPServer(ForkingMixIn, TCPServer): pass class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass三
server.handle_request() 只處理一個請求socket
server.forever() 處理多個請求,一直執行ide
簡單的接收客戶端發送的信息,並將其轉換成大寫,再返回給客戶端this
服務端: spa
# -*- coding: UTF-8 -*- import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): """ The request handler class for our server. It is instantiated once per connection to the server, and must override the handle() method to implement communication to the client. """ def handle(self): while True: # 屢次接收客戶端信息 # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) # just send back the same data, but upper-cased self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9999 # Create the server, binding to localhost on port 9999 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) # Activate the server; this will keep running until you # interrupt the program with Ctrl-C server.serve_forever()
客戶端:
# -*- coding: UTF-8 -*- import socket client = socket.socket() client.connect(('localhost', 9999)) while True: msg = input('>>:').strip() if not msg: continue else: client.send(msg.encode('utf-8')) upData = client.recv(1024) print(upData.decode())
到目前爲止咱們全部的c/s鏈接都同時只能處理一個客戶端請求,多個客戶端請求時,要等前面的客戶端請求關閉後才能執行,包括上面的代碼也是。若是想讓socketserver併發起來, 必須選擇使用如下一個多併發的類:
class socketserver.ForkingTCPServer class socketserver.ForkingUDPServer class socketserver.ThreadingTCPServer class socketserver.ThreadingUDPServer
只須要改變一個地方就能夠了
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
服務端:
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): def handle(self): while True: # self.request is the TCP socket connected to the client self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) # just send back the same data, but upper-cased self.request.sendall(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9999 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) server.serve_forever()