Python服務器開發 -- 網絡基礎

Python服務器開發 -- 網絡基礎

 
網絡由下往上分爲物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。HTTP是高層協議,而TCP/IP是個協議集,包過許多的子協議。...

網絡由下往上分爲物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。php

HTTP是高層協議,而TCP/IP是個協議集,包過許多的子協議。包括:傳輸層的 FTP,UDP,TCP協議等,網絡層的ip協議等,高層協議如HTTP,telnet協議等,HTTP是TCP/IP的一個子協議。html

socket是對TCP/IP協議的封裝和應用(程序員層面上)。也能夠說,TPC/IP協議是傳輸層協議,主要解決數據如何在網絡中傳輸,而HTTP是應用層協議,主要解決如何包裝數據。python

咱們在傳輸數據時,能夠只使用(傳輸層)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創建網絡鏈接的步驟:dom

創建Socket鏈接至少須要一對套接字,其中一個運行於客戶端,稱爲ClientSocket ,另外一個運行於服務器端,稱爲ServerSocket 。socket

套接字之間的鏈接過程分爲三個步驟:服務器監聽,客戶端請求,鏈接確認。

1。服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待鏈接的狀態,實時監控網絡狀態,等待客戶端的鏈接請求。

2。客戶端請求:指客戶端的套接字提出鏈接請求,要鏈接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要鏈接的服務器的套接字,指出服務器端套接字的地址和端口號,而後就向服務器端套接字提出鏈接請求。

3。鏈接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的鏈接請求時,就響應客戶端套接字的請求,創建一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式創建鏈接。而服務器端套接字繼續處於監聽狀態,繼續接收其餘客戶端套接字的鏈接請求。

HTTP連接的特色

HTTP協議即超文本傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網經常使用的協議之一,HTTP協議是創建在TCP協議之上的一種應用。

HTTP鏈接最顯著的特色是客戶端發送的每次請求都須要服務器回送響應,在請求結束後,會主動釋放鏈接。從創建鏈接到關閉鏈接的過程稱爲「一次鏈接」。

The Internet Protocol(協議)

IP就是一個32位無符號整數。IP地址經過DNS (Domain Name System) 數據庫映射到域名

1
2
3
4
5
6
7
#!/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實際上是一個文件描述符,不一樣於不一樣於本地文件,它鏈接了網絡上的一個文件。

一、建立一個UDP 本地鏈接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
import  socket, sys
=  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'

 

運行這段代碼:

1
2
3
4
5
6
7
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'

 

二、建立遠程鏈接並驗證收到的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import  random, socket, sys
=  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')。

相關文章
相關標籤/搜索