從零開始學Python第八周:網路編程基礎(socket),python第八周

來源:互聯網
上載者:User

從零開始學Python第八周:網路編程基礎(socket),python第八周
Socket網路編程一,Socket編程(1)Socket方法介紹

  • Socket是網路編程的一個抽象概念。通常我們用一個Socket表示“開啟了一個網路連結“,而開啟一個Socket需要知道目標電腦的IP地址和連接埠號碼,再指定協議類型即可。
  • 通訊端是一個雙向的通訊通道的端點。通訊端可能在溝通過程,進程之間在同一台機器上,或在不同的電腦之間的進程
  • 要建立一個通訊端,必須使用Socket模組的socket.socket()方法
  • 在socket模組中的一般文法:

s = socket.socket(socket_family,socket_type,protocol=0)

(3)TCP介紹
  • 大多數串連都是可靠的TCP串連。建立TCP串連時,主動發起串連的叫用戶端,被動響應串連的叫伺服器
  • 例如在瀏覽器中訪問新浪時,我們自己的電腦就是用戶端,瀏覽器會主動向新浪的伺服器發起串連。如果一切順利,新浪的伺服器接受了我們的串連,一個TCP串連就建立起來了,後面的通訊就是發送網頁內容了
(4)TCP編程示範-用戶端
  • 要建立一個基於TCP串連的Socket,代碼示範:
1 import socket2 3 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)4 s.connect(('www.sina.com.cn',80))

 

  • 建立TCP串連後,就可以向伺服器發送請求,要求返回首頁的內容,發送的文字格式設定必須符合HTTP標準,然後接收伺服器返回的資料,最後關閉串連
(5)TCP編程示範-伺服器
  • 和用戶端編程相比,伺服器編程就要複雜一些,伺服器處理序首先要綁定一個連接埠並監聽來自其他用戶端的串連。如果某個用戶端串連過來了,伺服器就與該用戶端建立Socket串連,隨後的通訊就靠這個Socket串連了
  • 編寫一個簡單的伺服器程式,它接收用戶端串連,把用戶端發過來的字串加上Hello再發回去,代碼示範:
 1 import socket 2  3 Host = 'locakhost'      #監聽的IP地址 4 port = 8888             #監聽的連接埠 5 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #建立通訊端 6 s.bind(Host,port)       #綁定IP地址和連接埠 7 s.listen(5)             #開始監聽 8 conn,addr = s.accept()  #接受一個新串連 9 data = conn.recv(1024)  #接收用戶端字串10 conn.sendall(data+'Hello') #發送字串給用戶端

 

  • 需要注意的是:同一個連接埠,被一個Socket綁定了以後,就不能被別的Socket綁定了
(6)UDP介紹
  • TCP是建立可靠串連,並且通訊雙方都可以以流的形式發送資料。相對TCP,UDP則是面向不需連線的協議
  • 使用UDP協議時,不需要建立串連,只需要知道對方的IP地址和連接埠號碼,就可以直接發資料包。但是,能不能到達並不清楚。
  • 雖然用UDP傳輸資料不可靠,但它的優點是和TCP比,速度快,對於不要求可靠到達的資料,就可以使用UDP協議
(7)UDP編程示範
  • 通過UDP協議傳輸資料。和TCP類似,使用UDP的通訊雙方也分為用戶端和伺服器。伺服器首先需要綁定連接埠,代碼示範:
1 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)2 s.bind(('127.0.0.1',9999))   #連接埠綁定

 

  • 用戶端使用UDP時,首先仍然建立基於UDP的Socket,但是不需要調用connect(),直接通過sendto()給伺服器發資料,代碼示範:
1 s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)2 for data in ['Michael','Tracy','Sarah']:3     s.sendto(data)

 

  • 需要注意的是:伺服器綁定UDP連接埠和TCP連接埠互不衝突,UDP的9999連接埠與TCP的9999連接埠可以各自綁定
二,TCP編程舉例

Socket是網路編程的一個抽象概念。通常我們用一個Socket表示“開啟了一個網路連結”,而開啟一個Socket需要知道目標電腦的IP地址和連接埠號碼,再指定協議類型即可。

  • 用戶端

舉個例子,當我們在瀏覽器中訪問新浪時,我們自己的電腦就是用戶端,瀏覽器會主動向新浪的伺服器發起連結。如果一切順利,新浪的伺服器接收了我們的串連,一個TCP串連就建立起來了,後面的通訊就是發送網頁內容。

所以,我們要建立一個基於TCP串連的Socket,可以這樣做:

1 # 匯入socket庫2 import socket3 # 建立一個socket:4 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)5 # 建立串連6 s.connect(('www.sina.com.cn',80))

建立Socket時,AF_INET指定使用IPv4協議,如果要用更先進的IPv6,就指定為AF_INET6。SOCK_STREAM指定使用面向流的TCP協議,這樣,一個Socket對象就建立成功,但是還沒有建立串連。

用戶端要主動發起TCP串連,必須知道伺服器的IP地址和連接埠號碼。新浪網站的IP地址可以用網域名稱www.sina.com.cn自動轉換到IP地址,而Web服務的標準連接埠80.

因此,我們串連新浪伺服器的代碼如下:

s = connect(('www.sina.com.cn',80))

注意參數是一個tuple,包含地址和連接埠號碼。

建立TCP串連後,我們就可以向新浪伺服器發送請求,要求返回首頁的內容:

# 發送資料:s.send('GET / HTTP/1.1\r\nHost:www.sina.com.cn\r\nConnection: close\r\n\r\n')

 

TCP串連建立的是雙向通道,雙方都可以同時給對方發資料。但是誰先發誰後發,怎麼協調,要根據具體的協議來決定。例如,HTTP協議規定用戶端必須先發請求給伺服器,伺服器收到後才發資料給用戶端。

發送的文字格式設定必須符合HTTP標準,如果格式沒問題,接下來就可以接收新浪伺服器返回的資料了:

 1 # 接收資料: 2 buffer = [] 3 while True: 4     # 每次最多接收1K位元組: 5     d = s.recv(1024) 6     if d: 7         buffer.append(d) 8     else: 9         break10     data = ''.join(buffer)

 

接收資料時,調用recv(max)方法,一次最多接收指定的位元組數,因此,在一個while迴圈中反覆接收,直到recv()返回空資料,表示接收完畢,退出迴圈。

當我們接收完資料後,調用close()方法關閉Socket,這樣,一次完整的網路通訊就結束了:

# 關閉串連s.close()

 

接收到的資料包括HTTP頭和網頁本身,我們只需要把HTTP頭和網頁分離一下,把HTTP頭列印出來,網頁內容儲存到檔案:

header,html = data.split('\r\n\r\n',1)print header# 把接收的資料寫入檔案:with open('sina.html','wb') as f:    f.write(html)

 

 

現在,只需要在瀏覽器中開啟這個sina.html檔案,就可以看到新浪的首頁了。

  • 伺服器

和用戶端編程相比,伺服器編程就要複雜一些。

伺服器處理序首先要綁定一個連接埠並監聽來自其他用戶端的串連。如果某個用戶端串連過來了,伺服器就與該用戶端建立Socket串連,隨後的通訊就靠這個Socket串連了。

所以,伺服器會開啟固定連接埠(比如80)監聽,每來一個用戶端串連,就建立該Socket串連。由於伺服器會開啟固定連接埠(比如80)監聽,每來一個用戶端串連,就建立該Socket串連。由於伺服器會有大量來自用戶端的串連,所以,伺服器要能夠區分一個Socket串連是和哪個用戶端綁定的。一個Socket依賴4項:伺服器位址,伺服器連接埠,用戶端地址,用戶端連接埠來唯一確定一個Socket。

但是伺服器還需要同時響應多個用戶端請求,所以,每個串連都需要一個新的進程或者新的線程來處理,否則,伺服器一次就只能服務一個用戶端了。

我們來編寫一個簡單的伺服器程式,它接收用戶端串連,把用戶端發過來的字串加上Hello再發回去。

首先,建立一個基於IPv4和TCP協議的Socket:

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

 

然後,我們要綁定監聽的地址和連接埠。伺服器可能有多塊網卡,可以綁定到某一塊網卡的IP地址上,也可以0.0.0.0綁定到所有的網路地址,還可以用127.0.0.1綁定到本機地址。127.0.0.1是一個特殊的IP地址,表示本機地址,如果綁定到這個地址,用戶端必須同時在本機運行才能串連,也就是說,外部的電腦無法串連進來。

連接埠號碼需要預先指定。因為我們寫的這個服務不是標準服務,所以用9999這個連接埠號碼。請注意,小於1024的連接埠號碼必須要有管理員權限才能綁定:

# 監聽連接埠s.bind(('127.0.0.1',9999))

 

  緊接著,調用listen()方法開始監聽連接埠,傳入的參數指定等待串連的最大數量:

s.listen(5)print 'Waiting for connection...'

 

  接下來,伺服器程式通過一個永久迴圈來接受來自用戶端的串連,accept()會等待並返回一個用戶端串連:

while TAG:    # 接受一個新串連    conn,addr = s.accept()    # 建立一個新線程處理TCP串連     t = threading.Thread(target=tcplink,args=(conn,addr))     t.start()

 

  每個串連都必須建立新線程(或進程)來處理,否則,單線程在處理串連的過程中,無法接受其他用戶端的串連:

def tcplink(conn,addr):    print ('Accept new connection form {0}'.format(addr))    conn.send('Welcome!')    while True:        data = conn.recv(1024)        time.sleep(1)        if data == 'exit' or not data:            break        socket.send('Hello,{0}!'.format(data))    conn.close()    print ('Connection from {0} closed.'.format(addr))

 

  串連建立後,伺服器首先發一條歡迎訊息,然後等待用戶端資料,並加上Hello再發送給用戶端。如果用戶端發送了exit字串,就直接關閉串連

  要測試這個伺服器程式,我們還需要編寫一個用戶端程式:

  

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)# 建立串連:s.connect(('127.0.0.1',9999))# 接收歡迎訊息:print s.recv(1024)for data in ['Michael','Tracy','Sarah']:    # 發送資料:    s.send(data)    print s.recv(1024)s.send('exit')s.close()

 

  然後我們開啟兩個命令列視窗,一個運行伺服器程式,另一個運行用戶端程式,就可以看到效果。

  需要注意的是,用戶端程式運行完畢就退出了,而伺服器程式會永遠運行下去,必須按Ctrl+C退出程式。

  • 小結

  用TCP協議進行Socket編程在Python中十分簡單,對於用戶端,要主動串連伺服器的IP和指定連接埠,對於伺服器,要首先監聽連接埠,然後,對每一個新的串連,建立一個線程或進程來處理。通常,伺服器程式會無限運行下去。

同一個連接埠,被一個Socket綁定了以後,就不能被別的Socket綁定了。 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.