1、 socketserver模組簡介
在python的socket編程中,實用socket模組的時候,是不能實現多個串連的,當然如果加入其它的模組是可以的,例如select模組,在這裡見到的介紹下socketserver模組。
socketserver,看其名字,就知道是一個socket的伺服器模組的使用,在這個模組中,主要也就是實現伺服器類的相關功能,在其中,也就是將socket模組和select模組進行了封裝,從而建立了一些基類供人使用。
2、 socketserver伺服器端和用戶端代碼
在socketserver模組中,主要就是使用一些伺服器類,從而簡化socket網路編程的方法,先上一段基本的伺服器代碼:
#!/usr/bin/env pythonimport SocketServerimport timeHOST = '192.168.1.60'PORT = 9999class MyHandler(SocketServer.BaseRequestHandler): def handle(self): while True: data = self.request.recv(1024) print data,self.client_address self.request.send( ' %s %s ' % (data,time.ctime())) if data == 'exit': breaks = SocketServer.ThreadingTCPServer((HOST,PORT),MyHandler)s.serve_forever()
在上述的代碼中,僅僅做了幾件事,先定義了一個類,也就是處理請求的類,從基類baserequesthandler繼承,主要就是重寫其中handle方法,告知伺服器如何來處理用戶端的請求。
然後建立了一個線程的TCP伺服器類,也就是通過多線程來進行應答用戶端,然後使用一直啟動並執行方法也就是serve_forever。
用戶端代碼如下:
#!/usr/bin/env pythonimport socketHOST = '192.168.1.60'PORT = 9999s = socket.socket()s.connect((HOST,PORT))while True: kel = raw_input('>>>') s.sendall(kel) print s.recv(1024) if kel == 'exit': breaks.close()
用戶端的代碼和socket編程的代碼基本相同,因為在socketserver模組中,主要是建立socke的服務端,而不涉及到用戶端,從而用戶端不需要修改代碼即可進行運行。
對比此段代碼和socket編程的區別是:可以和多個client端同時進行通訊。
[root@python 514]# ps -ef|grep pythonroot 8628 6091 0 12:56 pts/3 00:00:00 python server.pyroot 8629 32625 0 12:56 pts/0 00:00:00 python client.pyroot 8656 8634 0 12:56 pts/1 00:00:00 python client.py
在單純的socket編碼中,同時只能一個進行通訊,其他的串連會被阻塞。
3、 socketserver模組類介紹
在socketserver的預設要求處理常式中,是接收串連,得到請求,然後就關閉串連,從而也就是用戶端在迴圈的時候,必須每次都進行重新串連。
在上面的代碼中,重寫了事件處理的方法handle,在其中使用了迴圈,也就是一直保持和用戶端的串連。
請求處理的基類是BaseRequestHandler,其中一般需要重寫的方法就是handle方法,主要就是如何處理接下來的請求,在這個類裡,主要有三個方法,一個是setup,handle和finish方法,在調用這個類的時候,先調用setup進行一些初始化的工作,然後調用handle方法進行處理請求,然後調用finish方法,做一些關閉串連什麼的;在這個裡面最主要的參數self.request,也就是請求的socket對象,其中可以發送訊息sendall或者send,接收訊息的recv
在請求處理的子類中有兩個,一個是SreamRequestHandle和DatagramRequestHandle,在這個裡面重寫了基類的setup方法和finish方法,handle方法沒有重寫,因為這個是留給使用者做處理請求的方法,在這裡提供了幾個參數,一個self.rfile用來讀取資料的控制代碼,而self.wfile是用來發送訊息的控制代碼。
在使用rfile和wfile時候需要注意,在用戶端發送訊息的時候需要自己加上斷行符號,而在伺服器端需要使用readline方法來進行讀取,也就是讀取一行,如下所示伺服器端代碼:
#!/usr/bin/env pythonimport SocketServerimport timeHOST = '192.168.1.60'PORT = 9999class MyHandler(SocketServer.StreamRequestHandler): def handle(self): while True: data = self.rfile.readline().strip() print data,self.client_address self.wfile.write( ' %s %s ' % (data,time.ctime())) if data == 'exit': breaks = SocketServer.ThreadingTCPServer((HOST,PORT),MyHandler)s.serve_forever()
在使用rfile的時候,需要使用readline方法,否則會卡住請求的處理,而在用戶端代碼如下:
#!/usr/bin/env pythonimport socketHOST = '192.168.1.60'PORT = 9999s = socket.socket()s.connect((HOST,PORT))while True:# s = socket.socket()# s.connect((HOST,PORT)) kel = raw_input('>>>') s.sendall(kel + '\n') print s.recv(1024) if kel == 'exit': breaks.close()
在進行sendall資料的時候,需要加上''\n',表示此次發送的資料結束。
最基類的是伺服器類BaseServer類,其中定義了相關的方法,不能直接使用這個類,只能用來繼承,在子類中有倆,是作為同步伺服器類使用,TCPServer和UDPServer,這兩個類主要是和socket編程的時候是相同的,也就是會阻塞串連。TCPServer有一個子類為UNIXStreamServer,在UDPServer有一個子類為UnixDatagramServer,在最後的兩個子類中,是基於檔案同步的tcp和udp伺服器。
兩個混合類,一個是ForkingMixin,主要是用fork的,產生一個新的進程去處理;一個是ThreadingMixin,產生一個新的線程,主要是用來提供非同步處理的能力,其餘tcpserver和udpserver組合,又產生了新的四個類,從而提供非同步處理的能力。
在使用混合類和伺服器類的時候,注意混合類需要寫在前面,因為混合類重寫了伺服器類的方法,從而需要放在第一個位置。
總結:
python中的socketserver模組,主要是用來提供伺服器類,並且提供非同步處理的能力。