網路由下往上分為實體層、資料鏈結層、網路層、傳輸層、會話層、表示層、應用層。
HTTP是高層協議,而TCP/IP是個協議集,包過許多的子協議。包括:傳輸層的 FTP,UDP,TCP協定等,網路層的ip協定等,高層協定如HTTP,telnet協定等,HTTP是TCP/IP的子協定。
socket是對TCP/IP協定的封裝與應用(程式設計師層面上)。也可以說,TPC/IP協定是傳輸層協議,主要解決資料如何在網路中傳輸,而HTTP是應用層協議,主要解決如何包裝資料。
我們在傳輸資料時,可以只使用(傳輸層)TCP/IP協議,但是那樣的話,如果沒有應用層,便無法識別資料內容,如果想要使傳輸的資料有意義,則必須使用到應用層協議,應用層協定很多,例如HTTP、FTP、TELNET等,也可以自行定義應用層協定。 WEB使用HTTP協定作應用層協定,以封裝HTTP文字訊息,然後使用TCP/IP做傳輸層協定將它傳送到網路上。
而我們平常說的最多的socket是什麼呢,實際上socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個調用接口(API),透過Socket,我們才能使用TCP/IP協定.實際上,Socket跟TCP/IP協定沒有必然的聯繫。 Socket程式介面在設計的時候,就希望也能適應其他的網路協定。所以說,Socket的出現只是使得程式設計師更方便地使用TCP/IP協定棧而已,是對TCP/IP協定的抽象,從而形成了我們知道的一些最基本的函數接口,例如create、listen、connect、 accept、send、read和write等等。
TCP/IP只是一個協定棧,就像作業系統的運作機制一樣,必須具體實現,同時也要提供對外的操作介面。這個就像作業系統會提供標準的程式設計接口,像是win32程式介面一樣,TCP/IP也要提供可供程式設計師做網路開發所用的接口,這就是Socket程式介面。
有個比較形象的描述:HTTP是轎車,提供了封裝或顯示數據的具體形式;Socket是發動機,提供了網路通訊的能力。
實際上,傳輸層的TCP是基於網路層的IP協議的,而應用層的HTTP協議又是基於傳輸層的TCP協議的,而Socket本身不算是協議,就像上面所說,它只是提供了一個針對TCP或UDP程式設計的介面。
利用Socket建立網路連線的步驟:
建立Socket連線至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於伺服器端,稱為ServerSocket 。
套接字之間的連線過程分為三個步驟:伺服器監聽,客戶端請求,連線確認。
1。伺服器監聽:伺服器端套接字並不定位特定的客戶端套接字,而是處於等待連線的狀態,即時監控網路狀態,等待客戶端的連線要求。
2。客戶端請求:指客戶端的套接字提出連線請求,要連線的目標是伺服器端的套接字。為此,客戶端的套接字必須先描述它要連接的伺服器的套接字,指出伺服器端套接字的位址和連接埠號,然後就向伺服器端套接字提出連接請求。
3。連線確認:當伺服器端套接字監聽到或說接收到客戶端套接字的連線請求時,就回應客戶端套接字的請求,建立一個新的線程,把伺服器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連線。而伺服器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連線請求。
HTTP連結的特性
HTTP協定即超文本傳送協定(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機連網常用的協定之一,HTTP協定是建立在TCP協定之上的一種應用。
HTTP連線最顯著的特點是用戶端發送的每次請求都需要伺服器回送回應,在請求結束後,會主動釋放連線。從建立連線到關閉連線的過程稱為「一次連線」。
The Internet Protocol(協定)
IP就是一個32位元無符號整數。 IP位址透過DNS (Domain Name System) 資料庫對應到網域名稱
#!/usr/bin/env python # Foundations of Python Network Programming - Chapter 1 - getname.py import socket hostname = 'google.com' addr = socket.gethostbyname(hostname) print 'The address of', hostname, 'is', addr # The address of google.com is 173.194.72.113
Python網路程式設計:
Python提供了存取底層作業系統Socket介面的全部方法,也提供了一組加密和認證通訊的服務,SSL/TLS 。
Sockets其實是一個文件描述符,不同於不同於本地文件,它連接了網路上的一個文件。
1、建立一個UDP 本地連線:
#!/usr/bin/env python import socket, sys s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) MAX = 65535 PORT = 1060 if sys.argv[1:] == ['server']: s.bind(('127.0.0.1', PORT)) print 'Listening at', s.getsockname() while True: data, address = s.recvfrom(MAX) print 'The client at', address, 'says', repr(data) s.sendto('Your data was %d bytes' % len(data), address) elif sys.argv[1:] == ['client']: print 'Address before sending:', s.getsockname() s.sendto('This is my message', ('127.0.0.1', PORT)) print 'Address after sending', s.getsockname() data, address = s.recvfrom(MAX) # overly promiscuous - see text! print 'The server', address, 'says', repr(data) else: print >>sys.stderr, 'usage: udp_local.py server|client'
運行這段程式碼:
python filename.py server #Listening at ('127.0.0.1', 1060) #Address before sending: ('0.0.0.0', 0) #Address after sending ('0.0.0.0', 62892) #The server ('127.0.0.1', 1060) says 'Your data was 18 bytes' python filename.py client #The client at ('127.0.0.1', 62892) says 'This is my message'
2、建立遠端連線並驗證收到的資訊:
import random, socket, sys s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) MAX = 65535 PORT = 1060 if 2 <= len(sys.argv) <= 3 and sys.argv[1] == 'server': interface = sys.argv[2] if len(sys.argv) > 2 else '' s.bind((interface, PORT)) print 'Listening at', s.getsockname() while True: data, address = s.recvfrom(MAX) if random.randint(0, 1): print 'The client at', address, 'says:', repr(data) s.sendto('Your data was %d bytes' % len(data), address) else: print 'Pretending to drop packet from', address elif len(sys.argv) == 3 and sys.argv[1] == 'client': hostname = sys.argv[2] s.connect((hostname, PORT)) print 'Client socket name is', s.getsockname() delay = 0.1 while True: s.send('This is another message') print 'Waiting up to', delay, 'seconds for a reply' s.settimeout(delay) try: data = s.recv(MAX) except socket.timeout: delay *= 2 # wait even longer for the next request if delay > 2.0: raise RuntimeError('I think the server is down') else: break # we are done, and can stop looping print 'The server says', repr(data) else: print >>sys.stderr, 'usage: udp_remote.py server [ <interface> ]' print >>sys.stderr, ' or: udp_remote.py client <host>' sys.exit(2)
这里的s.connect((hostname, PORT))方法,可以让我们不用每次都调用s.sendto('This is my message', ('127.0.0.1', PORT))。直接调用
s.send('This is another message')。