Python網絡編程03----Python3.*中socketserver


       socketserver(在Python2.*中的是SocketServer模塊)是標准庫中一個高級別的模塊。用於簡化網絡客戶與服務器的實現(在前面使用socket的過程中,我們先設置了socket的類型,然后依次調用bind(),listen(),accept(),最后使用while循環來讓服務器不斷的接受請求。而這些步驟可以通過SocketServer包來簡化。)。模塊中,已經實現了一些可供使用的類。

       我們將再次實現之前的那個基本TCP的例子。你會注意到新實現與之前有很多相似之處,但你也要注意到,現在很多繁雜的事情已經被封裝好了,你不用再去關心那個樣板代碼了。例子給出的是一個最簡單的同步服務器。

       為了要隱藏實現的細節。我們現在寫程序時會使用類,這是與之前代碼的另一個不同。用面向對象的方法可以幫助我們更好的組織數據與邏輯功能。你也會注意到,我們的程序現在是“事件驅動”了。這就意味着,只有在事件出現的時候,程序才有“反應”。

       在之前的服務循環中,我們阻塞等待請求,有請求來的時候就處理請求,然后再回去繼續等待。現在的服務循環中,就不用在服務器里寫代碼了,改成定義一個處理器,服務器在收到進來的請求的時候,可以調用你的處理函數。

       類                 描述

 BaseServer               包含服務器的核心功能與混合(mix-in)類的鈎子功能。這個類用於派生,不要直接生成這個類的類對象,可以考慮使用 TCPServer 和UDPServer。 
TCPServer/UDPServer     基本的網絡同步 TCP/UDP 服務器 
UnixStreamServer/            基本的基於文件同步 TCP/UDP 服務器 
UnixDatagramServer 
ForkingMixIn/                      實現了核心的進程化或線程化的功能,用於與服務器類進行混合(mix-in),以提供一些異步特性。 
ThreadingMixIn                  不要直接生成這個類的對象 
ForkingTCPServer/            ForkingMixIn 和 TCPServer/UDPServer 的組合 
ForkingUDPServer 
ThreadingTCPServer/       ThreadingMixIn 和 TCPServer/UDPServer 的組合 
ThreadingUDPServer 
BaseRequestHandler       包含處理服務請求的核心功能。只用於派生新的類,不要直接生成這個類的對象,可以考慮使用 StreamRequestHandler 或DatagramRequestHandler 
StreamRequestHandler/   TCP/UDP 服務器的請求處理類的一個實現 
DatagramRequestHandler 

創建一個socketserverTCP服務器

[python]  view plain  copy
 
  1. from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH)    #可以通過as起別名  
  2. from time import ctime  
  3.    
  4. HOST = ''  
  5. PORT = 1234  
  6. ADDR = (HOST, PORT)  
  7.   
  8. class MyRequestHandler(SRH):  
  9.     def handle(self):  
  10.         print ('已經連接:', self.client_address)  
  11.         self.wfile.write(('[%s] %s' % (ctime(), self.rfile.readline().decode("UTF-8"))).encode("UTF-8"))  
  12.   
  13.   
  14. tcpServ = TCP(ADDR, MyRequestHandler)  
  15. print ('等待新的連接。。。。')  
  16.   
  17. tcpServ.serve_forever()  

我們從socketserver的StreamRequestHandler類中派生出一個子類,並重寫handle()函數。在BaseRequest 類中,這個函數什么也不做。在有客戶消息進來的時候,handle()函數就會被調用。StreamRequestHandler 類支持像操作文件對象那樣操作輸入輸出套接字。我們可以用readline()函數得到客戶消息,用write()函數把字符串發給客戶。

 

 

創建一個socketserverTCP客戶端

[python]  view plain  copy
 
  1. #coding=UTF-8  
  2. from socket import *  
  3. import sys  
  4. reload (sys)  
  5. sys.setdefaultencoding('utf8')     
  6.   
  7. HOST = '192.168.1.27'  
  8. PORT = 1234  
  9. BUFSIZE = 1024  
  10. ADDR = (HOST, PORT)  
  11.   
  12. while True:  
  13.     tcpCliSock = socket(AF_INET, SOCK_STREAM)  
  14.     tcpCliSock.connect(ADDR)  
  15.     data = raw_input('>')  
  16.     if not data:  
  17.         break  
  18.     tcpCliSock.send('%s\r\n' % data.encode("UTF-8"))  
  19.     data = tcpCliSock.recv(BUFSIZE).decode("UTF-8")  
  20.     if not data:  
  21.         break  
  22.     print (data.strip())  
  23.     tcpCliSock.close()  

使用socketserver處理多鏈接


       上面的例子一次只能連接一個客戶機並出力它的請求,如果要處理多連接問題,那么有三種主要的方法能實現這個目的:分叉(forking)、線程(threading)以及異步I/O(asynchronous I/O)。通過對socketserver服務器使用混入類(mix-in class),派生進程和線程很容易處理。即使要自己實現它們,這些方法也很容易使用。它們確實有缺點:分叉占據資源,並且如果有太多的客戶端時分叉不能很好分叉(盡管如此,對於合理數量的客戶端,分叉在現代的UNIX或者Linux系統中是很高效的,如果有一個多CPU系統,那系統效率會更高);線程處理能導致同步問題。使用socketserver框架創建分叉或者線程服務器非常簡單:

 

分叉服務器:

 

[python]  view plain  copy
 
  1. from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH,ForkingMixIn as FMI)   #變動位置  
  2. from time import ctime  
  3.    
  4. HOST = ''  
  5. PORT = 1234  
  6. ADDR = (HOST, PORT)  
  7.    
  8. class Server(FMI, TCP):                                                                         #變動位置  
  9.     pass  
  10.   
  11. class MyRequestHandler(SRH):  
  12.     def handle(self):  
  13.         print ('已經連接:', self.client_address)  
  14.         self.wfile.write(('[%s] %s' % (ctime(), self.rfile.readline().decode("UTF-8"))).encode("UTF-8"))  
  15.   
  16. tcpServ = Server(ADDR, MyRequestHandler)                                                         #變動位置  
  17. print ('等待新的連接。。。。')  
  18. tcpServ.serve_forever()  

 

 

多線程SocketServer服務器:

[python]  view plain  copy
 
  1. from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH,ThreadingMixIn as TMI)   #變動位置  
  2. from time import ctime  
  3.    
  4. HOST = ''  
  5. PORT = 1234  
  6. ADDR = (HOST, PORT)  
  7. class Server(TMI, TCP):                                         #變動位置  
  8.     pass  
  9.   
  10. class MyRequestHandler(SRH):  
  11.     def handle(self):  
  12.         print ('已經連接:', self.client_address)  
  13.         self.wfile.write(('[%s] %s' % (ctime(), self.rfile.readline().decode("UTF-8"))).encode("UTF-8"))  
  14.   
  15.   
  16. tcpServ = Server(ADDR, MyRequestHandler)                        #變動位置  
  17. print ('等待新的連接。。。。')  
  18. tcpServ.serve_forever()  


免責聲明!

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



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