socketserver 源码浅读
生活随笔
收集整理的這篇文章主要介紹了
socketserver 源码浅读
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
import SocketServer
class MyServer(SocketServer.BaseRequestHandler):def handle(self): #函數(shù)名必須是handle,源碼BaseRequestHandler預(yù)定義;print self.request,self.client_address,self.server #BaseRequestHandler的__init__定義好的;conn = self.request #每個(gè)連接的socketconn.sendall('歡迎致電 10086,請(qǐng)輸入1xxx,0轉(zhuǎn)人工服務(wù).')Flag = Truewhile Flag:data = conn.recv(1024)if data == 'exit':Flag = Falseelif data == '0':conn.sendall('通話可能會(huì)被錄音.balabala一大推')else:conn.sendall('請(qǐng)重新輸入.')
if __name__ == '__main__':server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer) #實(shí)例化ThreadingTCPServer,其實(shí)是繼承TCPServer類的初始化,需要傳入(server_address, RequestHandlerClass),RequestHandlerClass就是MyServer類。server.serve_forever() #啟動(dòng)服務(wù),用select一直在循環(huán)執(zhí)行,繼承自BaseServer類的方法serve_forever();
5、執(zhí)行 ThreadingMixIn.process_request 方法,創(chuàng)建一個(gè) “線程” 用來處理請(qǐng)求 ? ? 解釋:調(diào)用process_request方法時(shí),從繼承類廣度優(yōu)先原則,所以它先調(diào)用ThreadingMixIn類中的process_request 6、執(zhí)行?ThreadingMixIn.process_request_thread 方法 ? ? 解釋:t = threading.Thread(target = self.process_request_thread,args = (request, client_address))多線程模塊方法,調(diào)用self.process_request_thread,此時(shí)才真正啟動(dòng)了線程。 7、執(zhí)行 BaseServer.finish_request 方法,執(zhí)行?self.RequestHandlerClass() ?即:執(zhí)行 自定義 MyRequestHandler 的構(gòu)造方法(自動(dòng)調(diào)用基類BaseRequestHandler的構(gòu)造方法,在該構(gòu)造方法中又會(huì)調(diào)用自定義的MyRequestHandler的handle方法) ? ??解釋:連接創(chuàng)建完成,此時(shí)開始執(zhí)行handle方法中的內(nèi)容,開始和客戶端交互,執(zhí)行完,后面再執(zhí)行shutdown_request方法關(guān)閉連接。 import socket import threading import select def process(request, client_address):print request,client_addressconn = requestconn.sendall('歡迎致電 10086,請(qǐng)輸入1xxx,0轉(zhuǎn)人工服務(wù).')flag = Truewhile flag:data = conn.recv(1024)if data == 'exit':flag = Falseelif data == '0':conn.sendall('通過可能會(huì)被錄音.balabala一大推')else:conn.sendall('請(qǐng)重新輸入.') sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.bind(('127.0.0.1',8002)) sk.listen(5) while True:r, w, e = select.select([sk,],[],[],1)print 'looping'if sk in r:print 'get request'request, client_address = sk.accept()t = threading.Thread(target=process, args=(request, client_address))t.daemon = Falset.start() sk.close()
?
分析這段代碼
?
服務(wù)器啟動(dòng)程序后: 1、執(zhí)行 TCPServer.__init__ 方法,創(chuàng)建服務(wù)端Socket對(duì)象并綁定 IP 和 端口 ? ??解釋:class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass,ThreadingTCPServer先要執(zhí)行__init__構(gòu)造函數(shù),ThreadingMixIn里沒有,就去TCPServer類里去找 2、執(zhí)行 BaseServer.__init__ 方法,將自定義的繼承自SocketServer.BaseRequestHandler 的類 MyRequestHandle賦值給self.RequestHandlerClass ? ??解釋:TCPServer構(gòu)造方法中包含BaseServer.__init__(self, server_address, RequestHandlerClass),所以要把自己定義的類傳給BaseServer的構(gòu)造方法 3、執(zhí)行 BaseServer.server_forever 方法,While 循環(huán)一直監(jiān)聽是否有客戶端請(qǐng)求到達(dá) ... ? ? 解釋:serve_forever是BaseServer類中的方法,里面有個(gè)while循環(huán),一直調(diào)用select.select(),r, w, e = _eintr_retry(select.select, [self], [], [],poll_interval) 客戶端接入: 4、執(zhí)行BaseServer._handle_request_noblock方法 ? ??解釋:serve_forever的while循環(huán)里有一個(gè)判斷if?self?in?r:self._handle_request_noblock(),客戶端連接句柄發(fā)生變化就會(huì)把句柄放到r列表里,所以,觸發(fā)了_handle_request_noblock()。5、執(zhí)行 ThreadingMixIn.process_request 方法,創(chuàng)建一個(gè) “線程” 用來處理請(qǐng)求 ? ? 解釋:調(diào)用process_request方法時(shí),從繼承類廣度優(yōu)先原則,所以它先調(diào)用ThreadingMixIn類中的process_request 6、執(zhí)行?ThreadingMixIn.process_request_thread 方法 ? ? 解釋:t = threading.Thread(target = self.process_request_thread,args = (request, client_address))多線程模塊方法,調(diào)用self.process_request_thread,此時(shí)才真正啟動(dòng)了線程。 7、執(zhí)行 BaseServer.finish_request 方法,執(zhí)行?self.RequestHandlerClass() ?即:執(zhí)行 自定義 MyRequestHandler 的構(gòu)造方法(自動(dòng)調(diào)用基類BaseRequestHandler的構(gòu)造方法,在該構(gòu)造方法中又會(huì)調(diào)用自定義的MyRequestHandler的handle方法) ? ??解釋:連接創(chuàng)建完成,此時(shí)開始執(zhí)行handle方法中的內(nèi)容,開始和客戶端交互,執(zhí)行完,后面再執(zhí)行shutdown_request方法關(guān)閉連接。 import socket import threading import select def process(request, client_address):print request,client_addressconn = requestconn.sendall('歡迎致電 10086,請(qǐng)輸入1xxx,0轉(zhuǎn)人工服務(wù).')flag = Truewhile flag:data = conn.recv(1024)if data == 'exit':flag = Falseelif data == '0':conn.sendall('通過可能會(huì)被錄音.balabala一大推')else:conn.sendall('請(qǐng)重新輸入.') sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.bind(('127.0.0.1',8002)) sk.listen(5) while True:r, w, e = select.select([sk,],[],[],1)print 'looping'if sk in r:print 'get request'request, client_address = sk.accept()t = threading.Thread(target=process, args=(request, client_address))t.daemon = Falset.start() sk.close()
如精簡(jiǎn)代碼可以看出,SocketServer的ThreadingTCPServer之所以可以同時(shí)處理請(qǐng)求得益于?select?和?Threading?兩個(gè)東西,其實(shí)本質(zhì)上就是在服務(wù)器端為每一個(gè)客戶端創(chuàng)建一個(gè)線程,當(dāng)前線程用來處理對(duì)應(yīng)客戶端的請(qǐng)求,所以,可以支持同時(shí)n個(gè)客戶端鏈接(長(zhǎng)連接)。
來源:?http://www.cnblogs.com/wupeiqi/articles/5040823.html
轉(zhuǎn)載于:https://www.cnblogs.com/journey-mk5/p/9616242.html
總結(jié)
以上是生活随笔為你收集整理的socketserver 源码浅读的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Primer章课后编程问题
- 下一篇: SQLServer之PRIMARY KE