SocketServer創建一個網絡服務框架。它定義了類來處理TCP,UDP, UNIX streams 和UNIX datagrams上的同步網絡請求。
一、Server Types
有五個不同的服務器類在SocketServer中。
1.BaseServer定義了API, 而且他不是用來實例化和直接使用的。
2.TCPServer用作TCP/IP的socket通訊。
3.UDPServer使用datagram sockets。
4.UnixStreamServer和UnixDatagramServer使用Unix-domain sockets而且智能在unix平臺上使用。
二、Server Objects
構建一個服務器, 通過它來監聽請求的地址和請求的處理類(not instance)。
1.class SocketServer.BaseServer
這是模塊中所有服務器對象的超類,它定義了接口,實現大多數都在子類中完成。
2.BaseServer.fileno
返回一個整數文件描述符來表示哪個服務器正在監聽。這個函數最常見的傳遞給select.select(),允許監控多個相同處理過程的服務。
3.BaseServer.handle_request
處理單一的請求,這個函數會順序調用接下來的方法。get_request(),verify_request和proccess_request。
用戶提供handle()方法拋出一個異常,那么handle_error()方法會被調用。
self.timeout的時間內沒有收到請求,handle_timeout()和handle_request()將返回。
4.BaseServer.serve_forever
BaseServer.serve_forever(poll_interval=0.5),處理請求一直到明確的shutdown()請求。輪訓每隔poll_interval時間內關閉。忽略self.timeout,如果需要使用定時任務,需要使用其他線程。
5.BaseServer.shutdown
告訴serve_forever()循環停止。
6.BaseServer.RequestHandlerClass
用戶請求處理程序類,為每個請求創建這個類的一個實例。
三、Implementing a Server
如果你創建一個服務器,它通常可以重復使用現有的類和簡單的提供一個自定義請求處理的類。如果不符合需求,有幾種BaseServer方法覆蓋一個子類。
1.verify_request(reqeust, client_address): 必須返回一個布爾值,如果返回True,請求將被處理,如果返回False,請求將被拒絕。這個函數可以覆蓋來實現訪問控制服務。
2.process_request(request, client_address): 調用finish_request來創建一個RequestHandlerClass()的實例,如果需要該函數可以創建一個新的進程或協程來處理請求。
3.finish_request(request, client_address): 創建一個請求處理實例。調用handle()來處理請求。
四、Request Handlers
請求處理程序做的大部分工作接收傳入的請求,并決定采取何種行動。處理程序負責實現“協議”上的套接字層(例如,HTTP或xml - rpc)。從傳入的請求處理程序讀取請求數據通道,流程,和寫一個響應。有三個方法可以重寫。
1.setup(): 準備請求的請求處理程序, 就是初始化運行在handle之前。
2.handle(): 做真正的請求工作。解析傳入的請求,處理數據和返回響應。
3.finish(): 清理任意時間創建的setup()。
五、例子
下面例子展示了tcp, udp和異步
1.TCPServer 例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import SocketServer class MyHandler(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 = 'localhost' , 9999 server = SocketServer.TCPServer((HOST, PORT), MyHandler) server.serve_forever() |
2.UDPServr 例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle( self ): data = self .request[ 0 ].strip() socket = self .request[ 1 ] print '{} wrote:' . format ( self .client_address[ 0 ]) print data socket.sendto(data.upper(), self .client_address) if __name__ = = '__main__' : HOST, PORT = 'localhost' , 9999 server = SocketServer.UDPServer((HOST, PORT), MyHandler) server.serve_forever() |
3.異步例子
可以通過ThreadingMixIn和ForkingMixIn類來構造異步處理程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
import socket import threading import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle( self ): data = self .request.recv( 1024 ) curr_thread = threading.current_thread() response = '{}: {}' . format (curr_thread.name, data) self .request.sendall(response) class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass def client(ip, port, message): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) try : sock.sendall(message) response = sock.recv( 1024 ) print 'Received: {}' . format (response) finally : sock.close() if __name__ = = '__main__' : HOST, PORT = 'localhost' , 0 server = Server((HOST, PORT), MyHandler) ip, port = server.server_address serer_thread = threading.Thread(target = server.serve_forever) server_thread.daemon = True server_thread.start() print 'Server loop running in thread:' , server_thread.name client(ip, port, 'Hello World 1' ) client(ip, port, 'Hello World 2' ) client(ip, port, 'Hello World 3' ) server.shutdown() server.server_close() |
4.SocketServer 實現客戶端與服務器間非阻塞通信
(1)創建SocketServerTCP服務端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#創建SocketServerTCP服務器: import SocketServer from SocketServer import StreamRequestHandler as SRH from time import ctime host = 'xxx.xxx.xxx.xxx' port = 9999 addr = (host,port) class Servers(SRH): def handle( self ): print 'got connection from ' , self .client_address self .wfile.write( 'connection %s:%s at %s succeed!' % (host,port,ctime())) while True : data = self .request.recv( 1024 ) if not data: break print data print "RECV from " , self .client_address[ 0 ] self .request.send(data) print 'server is running....' server = SocketServer.ThreadingTCPServer(addr,Servers) server.serve_forever() |
(2)創建SocketServerTCP客戶端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
from socket import * host = 'xxx.xxx.xxx.xxx' port = 9999 bufsize = 1024 addr = (host,port) client = socket(AF_INET,SOCK_STREAM) client.connect(addr) while True : data = raw_input () if not data or data = = 'exit' : break client.send( '%s\r\n' % data) data = client.recv(bufsize) if not data: break print data.strip() client.close() |