標籤:
主題
- 用戶端/伺服器架構
- 通訊端:通訊終點
- 通訊端地址
- 連線導向與無串連通訊端
- Python中的網路編程
- SOCKET模組
- 通訊端對象方法
- TCP/IP用戶端和伺服器
- UDP/IP用戶端和伺服器
- SocketServer模組
- Twisted架構介紹
- 相關模組
1.用戶端伺服器架構 客戶<---->INTERNET<------->伺服器。客戶連上一個預先已知的伺服器,提出自己的請求,發送必要的資料,然後就等待伺服器返回的資料。
2.通訊端:通訊終點 通訊端是一種具有"通訊端點"概念的電腦網路資料結構。網路化的應用程式在開始任何通訊之前都需要建立通訊端、就像電話插口一樣,沒有它就會完全沒辦 法通訊。Python只支援AF_UNIX,AF_NETLINK,AF_INET家族,由於我們只關心網路編程所以我們都只用AF_INET。
3.通訊端地址 如果把通訊端比作電話介面----------即通訊的最底層結構,那主機與連接埠就像區號與電話號碼的一對組合。有了電話還不夠,你還要知道你要打電話給誰,往哪打。一個網際網路地址由網路通訊所必須的主機和連接埠組成,而且另一端一定要有人聽才可以。 合法的連接埠號碼範圍為0~65535,其中,小於1024的連接埠號碼為系統保留連接埠。
4.連線導向與無串連通訊端 (1)連線導向 無論使用哪個地址家族,通訊端的類型只有兩種,連線導向和無串連。連線導向即是在通訊前必須建立一條串連,就像跟朋友打電話一樣。實現這種串連的主要協 議就是傳輸控制通訊協定(TCP),要建立TCP通訊端就得在建立的時候指定通訊端類型為SOCK_STREAM。TCP通訊端採用SOCK_STREAM這 個名字型現了它最為流通訊端的特點,由於這些通訊端使用網際協議(ip)來尋找網路中的主機,所以這樣形成的整個系統,一般會有兩個協議(TCP和IP) 名的組合來描述,即TCP/IP。 (2)無串連 即無需串連就可以進行通訊。但這時,資料到達的順序、可靠性及不重複性就無法保證了。資料是整個發送的,不會像連線導向的協議那樣先被拆分成小塊。 實現這種串連的主要協議就是使用者資料包通訊協定(UDP)。要建立UDP通訊端就得在建立的時候指定通訊端類型為SOCK_DGRAM。"datagram"是"資料報"。
5.Python中的網路編程 我們將使用Python中的socket模組,模組中的socket()函數用來建立通訊端。要使用socket.socket()函數來建立通訊端,文法如下: socket.socket(socket_family,socket_type,protocol=0) 如前所述,Socket_family 不是 AF_VNIX 就是 AF_INET ,socket_type可以是SOCK_STREAM或是SOCK_DGRAM,protocol一般不填,預設為0。
6.SOCKET模組 例如建立一個TCP/IP的通訊端,你要這樣調用socket.socket()函數: tcpSock = socket.socket(socket.AF_INET,socket.SOCKET_STREAM) UDP/IP的通訊端 udpSock = socket.socket(socket.AF_INET,socket.SOCKET_DGRAM)由於socket模組中有太多的屬性,我們在這裡可以使用 “from module import *”的語句,我們就把socket模組裡所有屬性都帶到我們的命名空間裡了。 tcpSock = socket(AF_INET,SOCKET_STREAM)
7.通訊端對象(內建)方法 函數 描述 伺服器端通訊端函數
- s.bind( ) 綁定地址(主機名稱,連接埠號碼對)到通訊端
- s.listen( ) 開始TCP監聽
- s.accept( ) 被動接受TCP用戶端串連,(阻塞式)等待串連的到來。
用戶端通訊端函數
- s.connect( ) 主動初始化TCP伺服器串連。
- s.connect_ex( ) connect( )擴充版本,出錯時返回錯誤碼,而不是拋出異常。
公用用途的通訊端函數
- s,recv( ) 接受TCP資料。
- s.send( ) 發送TCP資料。
- s.sendall( ) 完整發送TCP資料。
- s.recvfrom( ) 接受UDP資料。
- s.sendto( ) 發送UDP資料。
- s.getpeername( ) 串連到當前通訊端的遠端地址(TCP串連)
- s.getsockname( ) 當前通訊端的地址。
- s.getsockopt( ) 返回當前通訊端的參數。
- s.setsockopt( ) 設定指定通訊端的參數。
- s.close( ) 關閉通訊端。
面向模組的通訊端函數
- s.setblocking( ) 設定通訊端的阻塞與非阻塞模式。
- s.settimeout( ) 設定阻塞通訊端操作的逾時時間。
- s.gettimeout( ) 得到阻塞通訊端操作的逾時時間。
面向檔案通訊端函數
- s.fileno( ) 通訊端檔案描述符。
- s.makefile( ) 建立一個與該通訊端關聯的檔案對象。
8.TCP/IP用戶端和伺服器
TCP伺服器設計虛擬碼: ss = socket() #建立伺服器通訊端 ss.bind() #把地址綁定到通訊端上 ss.listen() #監聽串連 inf_loop: #伺服器無線迴圈 cs = ss.accept() #接受用戶端串連 comm_loop: #通訊迴圈 cs.recv()/cs.send() #對話(接收與發送) cs.close() #關閉用戶端通訊端 ss.close() #關閉伺服器通訊端(可選) 所有通訊端都用socket.socket( )函數來建立。伺服器需要"坐在某個連接埠上"等待請求。所以它們必須要"綁定"到一個本地的地址上。一個簡單的(單線程)伺服器會調用accept( )函數等待串連的到來。預設情況下,accept( )函數是阻塞式的,即程式在串連到來之前會處於掛起狀態。通訊端也支援非阻塞狀態。 TCP時間戳記伺服器(tsTserv.py)建立一個能接受用戶端的訊息,在訊息前加一個時間戳記後返回TCP伺服器 from socket import * from time import ctime HOST = ‘‘ PORT = 21567 BUFSIZE = 1024 ADDR = (HOST,PORT) tcpSerSock = socket(AF_INET,SOCK_STREAM) tcpSerSock.bind( ADDR) tcpSerSock.listen(5) while True: print ‘waiting for 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( ) #關閉用戶端通訊端 TCP時間戳記用戶端(tsTclnt.py) 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()
9.UDP/IP用戶端和伺服器 UDP時間戳記伺服器(tsUserv.py) from socket import * from time import ctime HOST = ‘‘ PORT = 21567 BUFSIZ = 1024 ADDR = (HOST,PORT) udpSerSock = socket(AF_INET,SOCK_DGRAM) udpSerSock.bind(ADDR) while True: print ‘waiting for message......‘ data,addr = udpSerSock.recvfrom(BUFSIZ) udpSerSock.sendto(‘[%s] %s‘ % (ctime,data) ,addr) print ‘......received from and returned to:‘,addr udpSerSock.close() 建立一個UDP用戶端 from socket import * HOST = ‘localhost‘ PORT = "21567" BUFSIZ = 1024 ADDR = (HOST,PORT) udpCliSock = socket(AF_INET,SOCK_DGRAM) while Trus: data = raw_input(‘>‘) if not data: break udpCliSock.sendto(data,ADDR) data,ADDR = udpCliSock.recvfrom(BUFSIZ) if not data: break print data udpCliSock.close()
10.SocketServer模組 SocketServer 是標準庫中一個進階別的模組。用於簡化實現網路用戶端與伺服器所需的大量樣板代碼。該模組中,已經實現了一些可供使用的類。 SocketServer模組的類
| 類 |
描述 |
| BaseServer |
包含伺服器核心功能與混合(mix-in)類掛鈎;這個類只用於派生,所以不會產生這個類的執行個體;可以考慮使用TCPServer和UDPServer |
| TCPServer/UDPServer |
基本的網路同步TCP/UDP伺服器 |
| UnixStreamServer/UnixDatagramServer |
基本的基於檔案同步TCP/UDP伺服器 |
| ForkingMixIn/ThreadingMixIn |
實現了核心的進程化或線程化的功能;作為混合類,與伺服器類一併使用以提供一些非同步特性;這個類不會直接執行個體化。 |
| ThreadingTCPServer/ThreadingUDPServer |
ThreadingMixIn和TCPServer/UDPServer的組合 |
| BaseRequestHandler |
包含處理伺服器請求的核心功能,這個類只用於派生,所以不會產生這個類的執行個體可以考慮使用StreamRequestHandler 或 DatagramRequestHandler |
| StreamRequestHandler/DatagramRequestHandler |
用於TCP/UDP伺服器處理工具 |
| |
|
建立一個SocketServerTCP伺服器
在代碼中,先匯入我們的伺服器類,然後像之前一樣定義主機常量。主機常量後就是我們的要求處理常式類,然後是啟動代碼。 例 SocketServer 時間戳記TCP伺服器(TsTservss.py) from SocketServer import (TCPServer as TCP,StreamRequsetHandler as SRH) from time import ctime HOST = ‘‘ PORT = 21567 ADDR = (HOST,PORT) class MyRequestHandler(SRH): def handle(self): print ‘......connected from:‘,self.client_address self.wfile.write(‘[%s]%s‘ % (ctime(),self.rfile.readline())) tcpServ = TCP(ADDR,MyRequestHandler) print ‘waiting for connection...‘ tcpServ.serve_forever( ) 建立SocketServerTCP用戶端 from socket import * HOST = ‘localhost‘ PORT = 21567 BUFSIZ = 1024 ADDR = (HOST,PORT) while True: tcpCliSock = socket(AF_INET,SOCK_STREAM) tcpCliSock.connect(ADDR) data = raw_input(‘>‘) if not data: break tcpCliSock.send(‘%s\r\n‘ %data) data = tcpCliSock.recv(BUFSIZ) if not data: break print data.strip() tcpCliSock.close()
11.Twisted架構介紹 Twsited是一個完全事件驅動的網路架構。它允許你使用和開發完全非同步網路應用程式和協議。需要安裝它,系統中可以有:網路通訊協定、線程、安全和認 證、聊天/即時通訊、資料庫管理、關聯式資料庫整合、Web/internet、電子郵件、命令列參數、圖形介面整合等。 建立一個Twisted Reactor TCP伺服器 Twsited Reactor事件戳伺服器(tsTservTW.py) from twisted.internet import protocol,reactor from time import ctime PORT = 21567 class TSServProtocol(protocol.Protocol) -----------------------
課後題 16-1. 通訊端,連線導向與無串連有何區別?答:socket第二個參數不同。連線導向即tcp通訊函數為socket.socket(socket.AF_INET,socket.SOCK_STREAM),UDP通訊函數第二個參數為SOCK_DGRAM。16-2. 用戶端/伺服器架構。用你自己的語言描述這個架構。並給出幾個例子?答:伺服器在某連接埠等待用戶端的串連。怎麼說呢 client<------------>internet<------------->server16-3. 通訊端。TCP和UDP中,哪一種伺服器在接受串連後,把串連交給不同的通訊端處理與用戶端的通訊。答:TCP。16-4. 修改TCP(tsTclnt.py)和UDP(tsUclnt.py)用戶端,讓伺服器的名字不要在代碼裡寫死,要允許使用者指定一個主機名稱和連接埠,只有在兩個值都沒有輸入的時候才使用預設值。答:16-5. 網路互聯和通訊端。找到《python library reference》 樣本tcp用戶端/伺服器程式,實現它並讓它運行起來。先運行伺服器,然後是用戶端。http://www.python.org/doc /current/lib/Socket_Example.html 你認為這個伺服器太無聊,決定要修改伺服器,讓它能識別以下命令: data 伺服器將返回它的目前時間,即time.ctime(time.time())os 得到作業系統的資訊(os.name)ls 得到目前的目錄的檔案清單
python學習之【16】網路編程