使用套接字進行網絡編程,須要先了解一些有關網絡編程的背景信息。python
同步:所謂同步,就是在c端發出一個功能調用時,在沒有獲得結果以前,該調用就不返回。也就是必須一件一件事作,等前一件作完了才能作下一件事。ajax
例如普通B/S模式(同步):提交請求->等待服務器處理->處理完畢返回 這個期間客戶端瀏覽器不能幹任何事編程
異步:異步的概念和同步相對。當c端一個異步過程調用發出後,調用者不能馬上獲得結果。實際處理這個調用的部件在完成後,經過狀態、瀏覽器
通知和回調來通知調用者。服務器
例如 ajax請求(異步): 請求經過事件觸發->服務器處理(這是瀏覽器仍然能夠做其餘事情)->處理完畢網絡
阻塞:調用是指調用結果返回以前,當前線程會被掛起(線程進入非可執行狀態,在這個狀態下,cpu不會給線程分配時間片,即線程暫停運行)。函數只有在獲得結果以後纔會返回。有人也許會把阻塞調用和同步調用等同起來,實際上他是不一樣的。對於同步調用來講,不少時候當前線程仍是激活的,只是從邏輯上當前函數沒有返回而已。 例如,咱們在socket中調用recv函數,若是緩衝區中沒有數據,這個函數就會一直等待,直到有數據才返回。而此時,當前線程還會繼續處理各類各樣的消息。架構
非阻塞:非阻塞和阻塞的概念相對應,指在不能馬上獲得結果以前,該函數不會阻塞當前線程,而會馬上返回。框架
用取快遞來舉例就是:異步
阻塞:好比到你某個時候到A樓一層(假如是內核緩衝區)取快遞,可是你不知道快遞何時過來,你又不能幹別的事,只能死等着。但你能夠睡覺(進程處於休眠狀態),由於你知道快遞把貨送來時必定會給你打個電話(假定必定能叫醒你)。socket
非阻塞:若是用輪詢的方法,每隔5分鐘到A樓一層(內核緩衝區)去看快遞來了沒有。若是沒來,當即返回。而快遞來了,就放在A樓一層,等你去取。
使用到的主要模塊就是socket模塊。
通用TCP服務器的建立流程:
ss = socket() # 建立服務器套接字 ss.bind() # 套接字與地址綁定 ss.listen # 監聽鏈接 inf_loop: # 服務器無限循環 cs = ss.accept() # 接收客戶端鏈接 comm_loop: # 通訊循環 cs.recv()/cs.send() # 對話(接收/發送) cs.close() # 關閉客戶端套接字 ss.close() # 關閉服務器套接字(可選)
示例:
#!/usr/bin/python from socket import * from time import ctime HOST = '' PORT = 21567 BUFSIZ = 1024 ADDR = (HOST, PORT) tcpSerSock = socket(AF_INET, SOCK_STREAM) #創建TCP鏈接 tcpSerSock.bind(ADDR) tcpSerSock.listen(5) while True: print 'waiting for new connection...' tcpCliSock, addr = tcpSerSock.accept() print '...connected from:', addr while True: data = tcpCliSock.recv(BUFSIZ) if not data: break tcpCliSock.send('[%s] %s' % ( #返回客戶端發送的數據並帶上時間戳 ctime(), data)) tcpCliSock.close() tcpSerSock.close()
通用TCP客戶端的建立流程:
cs = socket() # 建立客戶端套接字 cs.connect() # 嘗試鏈接服務器 comm_loop: # 通訊循環 cs.send()/cs.recv() # 對話(發送/接收) cs.close() # 關閉客戶端套接字
示例:
#!/usr/bin/python from socket import * HOST = 'localhost' PORT = 21567 BUFSIZ = 1024 ADDR = (HOST, PORT) tcpCliSock = socket(AF_INET, SOCK_STREAM) tcpCliSock.connect(ADDR) while True: data = raw_input('> ') if not data: break tcpCliSock.send(data) data = tcpCliSock.recv(BUFSIZ) if not data: break print data tcpCliSock.close()
首先啓動服務端,再用客戶端鏈接。
客戶端顯示的是發送的數據和服務端返回帶時間戳的數據:
服務端的輸出只要是診斷性的:
建立UDP鏈接相比於TCP簡單的多,這裏就不演示了。
SocketServer簡化了網絡服務器的編寫。它有4個類:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。這4個類是同步進行處理的,另外經過ForkingMixIn和ThreadingMixIn類來支持異步。
建立服務器的步驟。首先,你必須建立一個請求處理類,它是BaseRequestHandler的子類並重載其handle()方法。其次,你必須實例化一個服務器類,傳入服務器的地址和請求處理程序類。最後,調用handle_request()通常是調用其餘事件循環或者使用select())或serve_forever()。集成ThreadingMixIn類時須要處理異常關閉。daemon_threads指示服務器是否要等待線程終止,要是線程互相獨立,必需要設置爲True,默認是False。
不管用什麼網絡協議,服務器類有相同的外部方法和屬性。該模塊在python3中已經改名爲socketserver。
這裏不做研究和演示。
Twisted是用Python實現的基於事件驅動的網絡引擎框架。Twisted誕生於2000年初,在當時的網絡遊戲開發者看來,不管他們使用哪一種語言,手中都鮮有可兼顧擴展性及跨平臺的網絡庫。Twisted的做者試圖在當時現有的環境下開發遊戲,這一步走的很是艱難,他們迫切地須要一個可擴展性高、基於事件驅動、跨平臺的網絡開發框架,爲此他們決定本身實現一個,並從那些以前的遊戲和網絡應用程序的開發者中學習,汲取他們的經驗教訓。
Twisted支持許多常見的傳輸及應用層協議,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。就像Python同樣,Twisted也具備「內置電池」(batteries-included)的特色。Twisted對於其支持的全部協議都帶有客戶端和服務器實現,同時附帶有基於命令行的工具,使得配置和部署產品級的Twisted應用變得很是方便。
本文不做研究和演示。
參考書籍:Python核心編程(第三版)