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模塊,主要是用來提供服務器類,並且提供異步處理的能力。