1. 程式人生 > >python 網絡編程

python 網絡編程

占用 揮手 博客 屬於 router 獲取 完整 以太網 復制

軟件開發的架構

我們了解的涉及到兩個程序之間通訊的應用大致可以分為兩種:

第一種是應用類:qq、微信、網盤、優酷這一類是屬於需要安裝的桌面應用

第二種是web類:比如百度、知乎、博客園等使用瀏覽器訪問就可以直接使用的應用

這些應用的本質其實都是兩個程序之間的通訊。而這兩個分類又對應了兩個軟件開發的架構~

1.C/S架構

C/S即:Client與Server ,中文意思:客戶端與服務器端架構,這種架構也是從用戶層面(也可以是物理層面)來劃分的。

這裏的客戶端一般泛指客戶端應用程序EXE,程序需要先安裝後,才能運行在用戶的電腦上,對用戶的電腦操作系統環境依賴較大。

技術分享圖片

2.B/S架構

B/S即:Browser與Server,中文意思:瀏覽器端與服務器端架構,這種架構是從用戶層面來劃分的。

Browser瀏覽器,其實也是一種Client客戶端,只是這個客戶端不需要大家去安裝什麽應用程序,只需在瀏覽器上通過HTTP請求服務器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。

技術分享圖片

網絡基礎

計算機網絡的發展及基礎網絡概念

問題:網絡到底是什麽?計算機之間是如何通信的?

早期 : 聯機

技術分享圖片

以太網 : 局域網與交換機

技術分享圖片

廣播

  主機之間“一對所有”的通訊模式,網絡對其中每一臺主機發出的信號都進行無條件復制並轉發,所有主機都可以接收到所有信息(不管你是否需要),由於其不用路徑選擇,所以其網絡成本可以很低廉。有線電視網就是典型的廣播型網絡,我們的電視機實際上是接受到所有頻道的信號,但只將一個頻道的信號還原成畫面。在數據網絡中也允許廣播的存在,但其被限制在二層交換機的局域網範圍內,禁止廣播數據穿過路由器,防止廣播數據影響大面積的主機。

ip地址與ip協議

  • 規定網絡地址的協議叫ip協議,它定義的地址稱之為ip地址,廣泛采用的v4版本即ipv4,它規定網絡地址由32位2進制表示
  • 範圍0.0.0.0-255.255.255.255
  • 一個ip地址通常寫成四段十進制數,例:172.16.10.1

mac地址

  head中包含的源和目標地址由來:ethernet規定接入internet的設備都必須具備網卡,發送端和接收端的地址便是指網卡的地址,即mac地址。

  mac地址:每塊網卡出廠時都被燒制上一個世界唯一的mac地址,長度為48位2進制,通常由12位16進制數表示(前六位是廠商編號,後六位是流水線號)

arp協議 ——查詢IP地址和MAC地址的對應關系

  地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取物理地址的一個TCP/IP協議。   主機發送信息時將包含目標IP地址的ARP請求廣播到網絡上的所有主機,並接收返回消息,以此確定目標的物理地址。   收到返回消息後將該IP地址和物理地址存入本機ARP緩存中並保留一定時間,下次請求時直接查詢ARP緩存以節約資源。   地址解析協議是建立在網絡中各個主機互相信任的基礎上的,網絡上的主機可以自主發送ARP應答消息,其他主機收到應答報文時不會檢測該報文的真實性就會將其記入本機ARP緩存;由此攻擊者就可以向某一主機發送偽ARP應答報文,使其發送的信息無法到達預期的主機或到達錯誤的主機,這就構成了一個ARP欺騙。ARP命令可用於查詢本機ARP緩存中IP地址和MAC地址的對應關系、添加或刪除靜態對應關系等。相關協議有RARP、代理ARP。NDP用於在IPv6中代替地址解析協議。

廣域網與路由器

技術分享圖片

路由器

  路由器(Router),是連接因特網中各局域網、廣域網的設備,它會根據信道的情況自動選擇和設定路由,以最佳路徑,按前後順序發送信號。 路由器是互聯網絡的樞紐,"交通警察"。目前路由器已經廣泛應用於各行各業,各種不同檔次的產品已成為實現各種骨幹網內部連接、骨幹網間互聯和骨幹網與互聯網互聯互通業務的主力軍。路由和交換機之間的主要區別就是交換機發生在OSI參考模型第二層(數據鏈路層),而路由發生在第三層,即網絡層。這一區別決定了路由和交換機在移動信息的過程中需使用不同的控制信息,所以說兩者實現各自功能的方式是不同的。   路由器(Router)又稱網關設備(Gateway)是用於連接多個邏輯上分開的網絡,所謂邏輯網絡是代表一個單獨的網絡或者一個子網。當數據從一個子網傳輸到另一個子網時,可通過路由器的路由功能來完成。因此,路由器具有判斷網絡地址和選擇IP路徑的功能,它能在多網絡互聯環境中,建立靈活的連接,可用完全不同的數據分組和介質訪問方法連接各種子網,路由器只接受源站或其他路由器的信息,屬網絡層的一種互聯設備。  

局域網

  局域網(Local Area Network,LAN)是指在某一區域內由多臺計算機互聯成的計算機組。一般是方圓幾千米以內。局域網可以實現文件管理、應用軟件共享、打印機共享、工作組內的日程安排、電子郵件和傳真通信服務等功能。局域網是封閉型的,可以由辦公室內的兩臺計算機組成,也可以由一個公司內的上千臺計算機組成。  

子網掩碼 

  所謂”子網掩碼”,就是表示子網絡特征的一個參數。它在形式上等同於IP地址,也是一個32位二進制數字,它的網絡部分全部為1,主機部分全部為0。比如,IP地址172.16.10.1,如果已知網絡部分是前24位,主機部分是後8位,那麽子網絡掩碼就是11111111.11111111.11111111.00000000,寫成十進制就是255.255.255.0。

  知道”子網掩碼”,我們就能判斷,任意兩個IP地址是否處在同一個子網絡。方法是將兩個IP地址與子網掩碼分別進行AND運算(兩個數位都為1,運算結果為1,否則為0),然後比較結果是否相同,如果是的話,就表明它們在同一個子網絡中,否則就不是。

技術分享圖片
比如,已知IP地址172.16.10.1和172.16.10.2的子網掩碼都是255.255.255.0,請問它們是否在同一個子網絡?兩者與子網掩碼分別進行AND運算,

172.16.10.1:10101100.00010000.00001010.000000001
255255.255.255.0:11111111.11111111.11111111.00000000
AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0

 

172.16.10.2:10101100.00010000.00001010.000000010
255255.255.255.0:11111111.11111111.11111111.00000000
AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0
結果都是172.16.10.0,因此它們在同一個子網絡。
例如

總結一下,IP協議的作用主要有兩個,一個是為每一臺計算機分配IP地址,另一個是確定哪些地址在同一個子網絡。

tcp協議和udp協議

用於應用程序之間的通信。如果說ip地址和mac地址幫我們確定唯一的一臺機器,那麽我們怎麽找到一臺機器上的一個軟件呢?

端口

  我們知道,一臺擁有IP地址的主機可以提供許多服務,比如Web服務、FTP服務、SMTP服務等,這些服務完全可以通過1個IP地址來實現。那麽,主機是怎樣區分不同的網絡服務呢?顯然不能只靠IP地址,因為IP 地址與網絡服務的關系是一對多的關系。實際上是通過“IP地址+端口號”來區分不同的服務的。

TCP協議

  當應用程序希望通過 TCP 與另一個應用程序通信時,它會發送一個通信請求。這個請求必須被送到一個確切的地址。在雙方“握手”之後,TCP 將在兩個應用程序之間建立一個全雙工 (full-duplex) 的通信。

  這個全雙工的通信將占用兩個計算機之間的通信線路,直到它被一方或雙方關閉為止。

技術分享圖片

技術分享圖片
TCP是因特網中的傳輸層協議,使用三次握手協議建立連接。當主動方發出SYN連接請求後,等待對方回答SYN+ACK[1],並最終對對方的 SYN 執行 ACK 確認。這種建立連接的方法可以防止產生錯誤的連接。[1] 
TCP三次握手的過程如下:
客戶端發送SYN(SEQ=x)報文給服務器端,進入SYN_SEND狀態。
服務器端收到SYN報文,回應一個SYN (SEQ=y)ACK(ACK=x+1)報文,進入SYN_RECV狀態。
客戶端收到服務器端的SYN報文,回應一個ACK(ACK=y+1)報文,進入Established狀態。
三次握手完成,TCP客戶端和服務器端成功地建立連接,可以開始傳輸數據了。
tcp的三次握手 技術分享圖片
建立一個連接需要三次握手,而終止一個連接要經過四次握手,這是由TCP的半關閉(half-close)造成的。
(1) 某個應用進程首先調用close,稱該端執行“主動關閉”(active close)。該端的TCP於是發送一個FIN分節,表示數據發送完畢。
(2) 接收到這個FIN的對端執行 “被動關閉”(passive close),這個FIN由TCP確認。
註意:FIN的接收也作為一個文件結束符(end-of-file)傳遞給接收端應用進程,放在已排隊等候該應用進程接收的任何其他數據之後,因為,FIN的接收意味著接收端應用進程在相應連接上再無額外數據可接收。
(3) 一段時間後,接收到這個文件結束符的應用進程將調用close關閉它的套接字。這導致它的TCP也發送一個FIN。
(4) 接收這個最終FIN的原發送端TCP(即執行主動關閉的那一端)確認這個FIN。[1] 
既然每個方向都需要一個FIN和一個ACK,因此通常需要4個分節。
註意:
(1) “通常”是指,某些情況下,步驟1的FIN隨數據一起發送,另外,步驟2和步驟3發送的分節都出自執行被動關閉那一端,有可能被合並成一個分節。[2] 
(2) 在步驟2與步驟3之間,從執行被動關閉一端到執行主動關閉一端流動數據是可能的,這稱為“半關閉”(half-close)。
(3) 當一個Unix進程無論自願地(調用exit或從main函數返回)還是非自願地(收到一個終止本進程的信號)終止時,所有打開的描述符都被關閉,這也導致仍然打開的任何TCP連接上也發出一個FIN。
無論是客戶還是服務器,任何一端都可以執行主動關閉。通常情況是,客戶執行主動關閉,但是某些協議,例如,HTTP/1.0卻由服務器執行主動關閉。[2] 
tcp的四次揮手

UDP協議

  當應用程序希望通過UDP與一個應用程序通信時,傳輸數據之前源端和終端不建立連接。

  當它想傳送時就簡單地去抓取來自應用程序的數據,並盡可能快地把它扔到網絡上。

tcp和udp的對比

TCP---傳輸控制協議,提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數據。TCP提供超時重發,丟棄重復數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
UDP---用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快。

技術分享圖片
現在Internet上流行的協議是TCP/IP協議,該協議中對低於1024的端口都有確切的定義,他們對應著Internet上一些常見的服務。這些常見的服務可以分為使用TCP端口(面向連接)和使用UDP端口(面向無連接)兩種。 
說到TCP和UDP,首先要明白“連接”和“無連接”的含義,他們的關系可以用一個形象地比喻來說明,就是打電話和寫信。兩個人如果要通話,首先要建立連接——即打電話時的撥號,等待響應後——即接聽電話後,才能相互傳遞信息,最後還要斷開連接——即掛電話。寫信就比較簡單了,填寫好收信人的地址後將信投入郵筒,收信人就可以收到了。從這個分析可以看出,建立連接可以在需要痛心地雙方建立一個傳遞信息的通道,在發送方發送請求連接信息接收方響應後,由於是在接受方響應後才開始傳遞信息,而且是在一個通道中傳送,因此接受方能比較完整地收到發送方發出的信息,即信息傳遞的可靠性比較高。但也正因為需要建立連接,使資源開銷加大(在建立連接前必須等待接受方響應,傳輸信息過程中必須確認信息是否傳到及斷開連接時發出相應的信號等),獨占一個通道,在斷開連接錢不能建立另一個連接,即兩人在通話過程中第三方不能打入電話。而無連接是一開始就發送信息(嚴格說來,這是沒有開始、結束的),只是一次性的傳遞,是先不需要接受方的響應,因而在一定程度上也無法保證信息傳遞的可靠性了,就像寫信一樣,我們只是將信寄出去,卻不能保證收信人一定可以收到。 
TCP是面向連接的,有比較高的可靠性, 一些要求比較高的服務一般使用這個協議,如FTP、Telnet、SMTP、HTTP、POP3等。
而UDP是面向無連接的,使用這個協議的常見服務有DNS、SNMP、QQ等。對於QQ必須另外說明一下,QQ2003以前是只使用UDP協議的,其服務器使用8000端口,偵聽是否有信息傳來,客戶端使用4000端口,向外發送信息(這也就不難理解在一般的顯IP的QQ版本中顯示好友的IP地址信息中端口常為4000或其後續端口的原因了),即QQ程序既接受服務又提供服務,在以後的QQ版本中也支持使用TCP協議了。
更多

互聯網協議與osi模型

互聯網協議按照功能不同分為osi七層或tcp/ip五層或tcp/ip四層

技術分享圖片

每層運行常見物理設備

技術分享圖片

每層運行常見的協議

技術分享圖片

1.一個程序如何在網絡上找到另一個程序?

首先,程序必須要啟動,其次,必須有這臺機器的地址,我們都知道我們人的地址大概就是國家\省\市\區\街道\樓\門牌號這樣字。那麽每一臺聯網的機器在網絡上也有自己的地址,它的地址是怎麽表示的呢?

就是使用一串數字來表示的,例如:100.4.5.6

技術分享圖片
IP地址是指互聯網協議地址(英語:Internet Protocol Address,又譯為網際協議地址),是IP Address的縮寫。IP地址是IP協議提供的一種統一的地址格式,它為互聯網上的每一個網絡和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差異。

IP地址是一個32位的二進制數,通常被分割為4個“8位二進制數”(也就是4個字節)。IP地址通常用“點分十進制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之間的十進制整數。例:點分十進IP地址(100.4.5.6),實際上是32位二進制數(01100100.00000100.00000101.00000110)。
什麽是ip地址? 技術分享圖片
"端口"是英文port的意譯,可以認為是設備與外界通訊交流的出口。
什麽是端口

因此ip地址精確到具體的一臺電腦,而端口精確到具體的程序。

2.osi七層模型

引子

須知一個完整的計算機系統是由硬件、操作系統、應用軟件三者組成,具備了這三個條件,一臺計算機系統就可以自己跟自己玩了(打個單機遊戲,玩個掃雷啥的)

如果你要跟別人一起玩,那你就需要上網了,什麽是互聯網?

互聯網的核心就是由一堆協議組成,協議就是標準,比如全世界人通信的標準是英語,如果把計算機比作人,互聯網協議就是計算機界的英語。所有的計算機都學會了互聯網協議,那所有的計算機都就可以按照統一的標準去收發信息從而完成通信了。

osi七層模型

人們按照分工不同把互聯網協議從邏輯上劃分了層級:

技術分享圖片

3.socket概念

socket層

技術分享圖片

理解socket

Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把復雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。

技術分享圖片
其實站在你的角度上看,socket就是一個模塊。我們通過調用模塊中已經實現的方法建立兩個進程之間的連接和通信。
也有人將socket說成ip+port,因為ip是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程序。
所以我們只要確立了ip和port就能找到一個應用程序,並且使用socket模塊來與之通信。
站在你的角度上看socket

3.套接字(socket)的發展史

套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 Unix,即人們所說的 BSD Unix。 因此,有時人們也把套接字稱為“伯克利套接字”或“BSD 套接字”。一開始,套接字被設計用在同 一臺主機上多個應用程序之間的通訊。這也被稱進程間通訊,或 IPC。套接字有兩種(或者稱為有兩個種族),分別是基於文件型的和基於網絡型的。

基於文件類型的套接字家族

套接字家族的名字:AF_UNIX

unix一切皆文件,基於文件的套接字調用的就是底層的文件系統來取數據,兩個套接字進程運行在同一機器,可以通過訪問同一個文件系統間接完成通信

基於網絡類型的套接字家族

套接字家族的名字:AF_INET

(還有AF_INET6被用於ipv6,還有一些其他的地址家族,不過,他們要麽是只用於某個平臺,要麽就是已經被廢棄,或者是很少被使用,或者是根本沒有實現,所有地址家族中,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由於我們只關心網絡編程,所以大部分時候我麽只使用AF_INET)

4.tcp協議和udp協議

TCP(Transmission Control Protocol)可靠的、面向連接的協議(eg:打電話)、傳輸效率低全雙工通信(發送緩存&接收緩存)、面向字節流。使用TCP的應用:Web瀏覽器;電子郵件、文件傳輸程序。

UDP(User Datagram Protocol)不可靠的、無連接的服務,傳輸效率高(發送前時延小),一對一、一對多、多對一、多對多、面向報文,盡最大努力服務,無擁塞控制。使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP)。

我知道說這些你們也不懂,直接上圖。

技術分享圖片

四.套接字(socket)初使用

基於TCP協議的socket

tcp是基於鏈接的,必須先啟動服務端,然後再啟動客戶端去鏈接服務端

server端

import socket
sk = socket.socket()
sk.bind((127.0.0.1,8898))  #把地址綁定到套接字
sk.listen()          #監聽鏈接
conn,addr = sk.accept() #接受客戶端鏈接
ret = conn.recv(1024)  #接收客戶端信息
print(ret)       #打印客戶端信息
conn.send(bhi)        #向客戶端發送信息
conn.close()       #關閉客戶端套接字
sk.close()        #關閉服務器套接字(可選)

client端

import socket
sk = socket.socket()           # 創建客戶套接字
sk.connect((127.0.0.1,8898))    # 嘗試連接服務器
sk.send(bhello!)
ret = sk.recv(1024)         # 對話(發送/接收)
print(ret)
sk.close()            # 關閉客戶套接字

問題:有的人在重啟服務端時可能會遇到

技術分享圖片

解決方法:

#加入一條socket配置,重用ip和端口
import socket
from socket import SOL_SOCKET,SO_REUSEADDR
sk = socket.socket()
sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
sk.bind((127.0.0.1,8898))  #把地址綁定到套接字
sk.listen()          #監聽鏈接
conn,addr = sk.accept() #接受客戶端鏈接
ret = conn.recv(1024)   #接收客戶端信息
print(ret)              #打印客戶端信息
conn.send(bhi)        #向客戶端發送信息
conn.close()       #關閉客戶端套接字
sk.close()        #關閉服務器套接字(可選)

python 網絡編程