1、 socketserver模塊簡介
在python的socket編程中,實用socket模塊的時候,是不能實現多個連接的,當然如果加入其它的模塊是可以的,例如select模塊,在這里見到的介紹下socketserver模塊。
socketserver,看其名字,就知道是一個socket的服務器模塊的使用,在這個模塊中,主要也就是實現服務器類的相關功能,在其中,也就是將socket模塊和select模塊進行了封裝,從而創建了一些基類供人使用。
2、 socketserver服務器端和客戶端代碼
在socketserver模塊中,主要就是使用一些服務器類,從而簡化socket網絡編程的方法,先上一段基本的服務器代碼:
#!/usr/bin/env python
import SocketServer
import time
HOST = '192.168.1.60'
PORT = 9999
class 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':
break
s = SocketServer.ThreadingTCPServer((HOST,PORT),MyHandler)
s.serve_forever()
在上述的代碼中,僅僅做了幾件事,先定義了一個類,也就是處理請求的類,從基類baserequesthandler繼承,主要就是重寫其中handle方法,告知服務器如何來處理客戶端的請求。
然后創建了一個線程的TCP服務器類,也就是通過多線程來進行應答客戶端,然后使用一直運行的方法也就是serve_forever。
客戶端代碼如下:
#!/usr/bin/env python
import socket
HOST = '192.168.1.60'
PORT = 9999
s = socket.socket()
s.connect((HOST,PORT))
while True:
kel = raw_input('>>>')
s.sendall(kel)
print s.recv(1024)
if kel == 'exit':
break
s.close()
客戶端的代碼和socket編程的代碼基本相同,因為在socketserver模塊中,主要是創建socke的服務端,而不涉及到客戶端,從而客戶端不需要修改代碼即可進行運行。
對比此段代碼和socket編程的區別是:可以和多個client端同時進行通信。
[root@python 514]# ps -ef|grep python root 8628 6091 0 12:56 pts/3 00:00:00 python server.py root 8629 32625 0 12:56 pts/0 00:00:00 python client.py root 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 python
import SocketServer
import time
HOST = '192.168.1.60'
PORT = 9999
class 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':
break
s = SocketServer.ThreadingTCPServer((HOST,PORT),MyHandler)
s.serve_forever()
在使用rfile的時候,需要使用readline方法,否則會卡住請求的處理,而在客戶端代碼如下:
#!/usr/bin/env python
import socket
HOST = '192.168.1.60'
PORT = 9999
s = 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':
break
s.close()
在進行sendall數據的時候,需要加上''\n',表示此次發送的數據結束。
最基類的是服務器類BaseServer類,其中定義了相關的方法,不能直接使用這個類,只能用來繼承,在子類中有倆,是作為同步服務器類使用,TCPServer和UDPServer,這兩個類主要是和socket編程的時候是相同的,也就是會阻塞連接。TCPServer有一個子類為UNIXStreamServer,在UDPServer有一個子類為UnixDatagramServer,在最后的兩個子類中,是基於文件同步的tcp和udp服務器。
兩個混合類,一個是ForkingMixin,主要是用fork的,產生一個新的進程去處理;一個是ThreadingMixin,產生一個新的線程,主要是用來提供異步處理的能力,其余tcpserver和udpserver組合,又產生了新的四個類,從而提供異步處理的能力。
在使用混合類和服務器類的時候,注意混合類需要寫在前面,因為混合類重寫了服務器類的方法,從而需要放在第一個位置。
總結:
python中的socketserver模塊,主要是用來提供服務器類,並且提供異步處理的能力。
