天天看點

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

華章程式員書庫 點選檢視第二章 點選檢視第三章

Python網絡程式設計(原書第2版)

Mastering Python Networking, Second Edition

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

[美] 埃裡克·周(Eric Chou)著

熊安萍 鄒洋 張璞 李鴻健 等譯

第1章

回顧TCP/IP協定簇和Python

歡迎來到網絡工程的新時代。在千禧年之際,我作為網絡工程師開始工作,這個角色與其他技術角色截然不同。網絡工程師利用特定領域的知識,管理和營運區域網路和廣域網,偶爾也會跨越到系統管理,但不用編寫代碼或了解程式設計概念。現在已不再是這種情況。多年來,DevOps和軟體定義網絡(SDN)以及其他因素大大模糊了網絡工程師、系統工程師和開發人員之間的界限。

你拿到這本書意味着你可能已經是網絡DevOps的采納者,或者你正在考慮走這條道路。也許你像我一樣做了多年的網絡工程師,并想知道Python程式設計語言為什麼這麼火。或者你可能已經熟悉Python,但想知道它在網絡工程中的應用是什麼。如果你屬于這些陣營中的任何一個,或者隻是對網絡工程領域的Python感到好奇,我相信這本書适合你:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

目前市面上已經存在很多深入研究網絡工程和Python主題的書籍。在本書中我不想去重複他們的工作。相反,本書假設你具有管理網絡的實踐經驗,并且對網絡協定和Python語言有基本了解。你不需要成為Python或網絡工程專家,但應該從本章的綜述中了解基本概念。本章的其餘部分将會設定必要的知識儲備等級,以充分利用本書。如果你想了解本章内容,可以使用許多免費或低成本資源來加快速度。這裡推薦免費的Khan學院(

https://www.khanacademy.org/

)和Python教程(

https://www.python.org/

)。

本章将快速通路相關的網絡主題。根據我在現場工作的經驗,典型的網絡工程師或開發人員可能不記得完成日常任務時确切的TCP狀态機(我知道我不記得了),卻更熟悉OSI模型的基礎知識、TCP和UDP操作、不同IP頭字段和其他基礎概念。

我們還将回顧Python語言的概要,對于那些沒有每天使用Python語言的讀者來說,足以繼續學習本書的其餘部分。

特别地,我們會涉及下面的主題:

  • 網際網路的概述。
  • OSI和用戶端–服務端模型。
  • TCP、UDP和IP協定簇。
  • Python文法、類型、操作符和循環。
  • 用于擴充Python的函數、類和包。

當然,本章提供的資訊并非詳盡無遺,請檢視參考資料以擷取更多資訊。

1.1 網際網路概述

什麼是網際網路?依據你的背景,對于這個看似簡單的問題可能會給出不同的答案。不同的人對網際網路有不同的了解,年輕人、老年人、學生、老師、商業人士、詩人對這個問題會給出不同的答案。

對于一個網絡工程師而言,網際網路是一個由大小網絡連接配接在一起組成的全球計算機網絡。換句話說,它是一個沒有中心所有者的網絡。以你的家庭網絡為例,它可以由一個家庭以太網交換機和連接配接智能手機、平闆電腦、計算機以及電視的無線接入點組成,以實作裝置間通信。這是你的區域網路(LAN)。當你的家庭網絡需要與外部世界通信時,它會将資訊從LAN傳遞到更大的網絡,通常稱為網際網路服務提供商(ISP)。你的ISP通常由邊緣節點組成,這些邊緣節點将流量聚合到其核心網絡。核心網絡的功能是通過更高速的網絡互連這些邊緣網絡。在特殊的邊緣節點,你的ISP已連接配接到其他ISP,以便将你的流量恰當地傳遞到目的地。從目标網絡到家用計算機、平闆電腦或智能手機的傳回路徑可能會也可能不會通過相同路徑傳回到你的裝置,而來源和目标網絡保持不變。

讓我們來看看組成這個網絡的元件。

1.1.1 伺服器、主機和網絡元件

主機是網絡上與其他節點通信的終端節點。在當今世界,主機可以是傳統計算機,也可以是智能手機、平闆電腦或電視。随着物聯網(IoT)的興起,主機的廣泛定義可以擴充到包括IP錄影機、電視機頂盒,以及我們用于農業、耕作、汽車等不斷增加的各種類型的傳感器。随着連接配接到網際網路的主機數量激增,所有這些主機都需要進行尋址、路由和管理。對以上這些特有的網絡的需求從未如此強烈。

我們上網的大部分時間都是通過請求擷取服務。請求的服務可以是浏覽網頁、發送或接收電子郵件、傳輸檔案等。這些服務由伺服器提供,顧名思義,伺服器為多個節點提供服務,是以通常具有更進階别的硬體規範。在某種程度上,伺服器是網絡上的特殊超級節點,為其他節點提供額外的能力。我們稍後将在用戶端–伺服器模型中看到。

如果你将伺服器和主機視為城市和城鎮,則網絡元件是将它們連接配接在一起的道路和高速公路。實際上,在描述跨越全球傳輸不斷增加的比特和位元組的網絡元件時,會想到資訊高速公路這一術語。在OSI模型中我們将看到以比特(bit)傳輸的網絡元件,它們是第一層到第三層裝置。它們是用于引導流量的第二層和第三層的路由器和交換機,以及諸如光纖電纜、同軸電纜、雙絞銅線和一些DWDM裝置之類的第一層傳輸裝置,在此僅舉幾例。

總而言之,主機、伺服器和網絡元件構成了我們今天所知的網際網路。

1.1.2 資料中心的興起

在上一節中,我們看到了伺服器、主機和網絡元件在網際網路中的不同角色。由于伺服器需要更高的硬體能力,它們通常一起放置在一個中央位置,以便有效管理。我們通常将這些中央位置稱為資料中心。

1.1.2.1 企業資料中心

在典型的企業中,公司通常需要内部工具,例如電子郵件、文檔存儲、銷售跟蹤、訂購、HR工具和知識共享内聯網。這些服務轉換為檔案和郵件伺服器、資料庫伺服器和Web伺服器。與使用者計算機不同,這些通常是需要大量電源、冷卻和網絡連接配接的高端計算機。硬體的副作用也是來源于硬體産生的噪聲。它們通常位于企業中稱為主配線架(MDF)的中心位置,以提供必要的供電、電源備援、冷卻和網絡連接配接。

要連接配接到MDF,使用者的流量在捆綁并連接配接到MDF之前,使用者的通信通常聚合在靠近使用者的位置,有時稱為中間配線架(IDF)。IDF-MDF分布遵循企業大樓或校園的實體布局并不罕見。例如,每個建築物樓層可以包含IDF,該IDF聚合到另一層的MDF。如果企業由多個建築物組成,則可以通過在将建築物連接配接到企業資料中心之前組合建築物的流量來進行進一步的聚合。

企業資料中心一般遵循三層網絡設計。這些層是接入層、彙聚層和核心層。接入層類似于每個使用者連接配接的端口,IDF可以被認為是彙聚層,而核心層由到MDF的連接配接和企業資料中心組成。當然,這是普遍的企業網絡,某些網絡不會遵循相同的模型。

1.1.2.2 雲資料中心

随着雲計算、軟體以及基礎設施服務的興起,資料中心雲提供商的建構是超大規模的。由于它們所容納的伺服器數量很大,它們通常需要比任何企業資料中心更高的電力、冷卻、網絡速度和供給能力。即使在雲提供商資料中心工作多年之後,每次通路雲提供商資料中心時,我仍然驚訝于它們的規模。實際上,雲資料中心非常龐大且耗電量巨大,是以它們通常靠近發電廠建造,在那裡它們可以獲得最便宜的電價,而不會在電力運輸過程中損失太多能耗。它們的冷卻需求非常大,通常建構在一個普遍寒冷的氣候下,這樣在需要時僅打開門窗就可以保持伺服器運作在安全的溫度。任何搜尋引擎來到像亞馬遜、微軟、谷歌和Facebook的科學化建構和管理的雲資料中心時,都會給你一些驚人的數字:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

在雲提供商規模上,它們需要提供的服務通常不具有成本效益,或者不能切實地安裝在單個伺服器中。它們分布在一組伺服器之間,有時跨越許多不同的機架,為所有者提供備援和靈活性的服務。延遲和備援需求給網絡帶來了巨大的壓力。互連的數量相當于網絡裝置的爆炸式增長,這轉化為此網絡裝置需要進行機架設定、配置和管理的次數。典型的網絡設計将是一個多級的CLOS網絡:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

在某種程度上,資料中心的網絡自動化是保證快速和可靠性所必需的。如果我們跟随傳統的方式通過終端和指令行接口來管理網絡裝置,所需的工時數将不允許在合理的時間内有可供使用的服務。這還沒有考慮人工重複易于出錯、低效和可怕的工程人才的浪費。

雲資料中心是我很多年前開始用Python實作網絡自動化的地方,自此從未回頭。

1.1.2.3 邊緣資料中心

如果我們在資料中心層擁有足夠的計算能力,為什麼要将資料保留在這些資料中心,而不保留到其他地方呢?來自世界各地的用戶端的所有連接配接都可以路由回提供服務的資料中心伺服器,就到此為止了嗎?答案當然取決于用例。将請求和會話從用戶端一直路由到大型資料中心的最大限制是傳輸中産生的延遲。換句話說,高延遲是網絡的瓶頸。延遲永遠不會為零:即使同光在真空中傳播的速度一樣快,它仍然需要時間進行實體傳輸。在現實世界中,當資料包穿過多個網絡時(有時通過海底電纜、慢速衛星鍊路、3G或4G蜂窩鍊路或Wi-Fi連接配接),延遲将遠遠高于真空中的光。

解決方案?減少最終使用者通過的網絡數量。在使用者接入網絡的邊緣盡可能更近地連接配接到使用者,并在邊緣位置放置足夠的資源來為請求服務。讓我們花點時間想象你正在建構下一代視訊流服務。為了提高客戶對平滑流媒體的滿意度,你可能希望将視訊伺服器放置在盡可能靠近客戶的位置,要麼是在客戶的ISP内部,要麼非常靠近客戶的ISP。此外,視訊伺服器叢集的上遊不是僅連接配接到一個或兩個ISP,而是連接配接到所有ISP以減少跳數。所有連接配接都将具有所需的帶寬,以減少高峰時段的延遲。這種需求助長了大型ISP的邊緣資料中心與内容提供商的對等交換。即使網絡裝置的數量不如雲資料中心那麼多,它們也能得益于網絡自動化帶來的增強的可靠性、安全性和可視性。

我們将在本書後面的章節中介紹安全性和可視性。

1.2 OSI模型

沒有首先回顧開放系統互連(OSI)模型的網絡書籍是不完整的。該模型是一個概念模型,将電信功能元件化為不同的層。該模型定義了7層,每層獨立地位于另一層之上,隻要它們遵循定義的結構和特征即可。例如,在網絡層中,IP可以位于不同類型的資料鍊路層(例如以太網或幀中繼)之上。OSI參考模型是将不同和多樣化技術标準化為人們能夠認同的一套通用語言的好方法。這大大減少了各方在特定層的工作範圍,并允許他們深入檢視特定任務,而不必過多擔心相容性:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

OSI模型最初是在20世紀70年代後期開展的,後來由國際标準化組織(ISO)和現在稱為國際電信聯盟(ITU-T)的電信标準化部門聯合出版。該模型被廣泛接受并通常在引入電信領域的新話題時被提及。

在OSI模型開發的同一時期,網際網路正在形成。原始設計者使用的參考模型通常指的是TCP/IP模型。傳輸控制協定(TCP)和網際網路協定(IP)是設計中包含的原始協定簇。這有點類似于OSI模型,因為它們将端到端資料通信劃分為抽象層。不同的是,模型在應用層中組合了OSI模型的第5~7層,而實體層和資料鍊路層在鍊路層中組合在一起:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

OSI和TCP/IP模型都可用于為端到端資料通信提供标準。但是,在大多數情況下,我們更多指的是TCP/IP模型,因為這是網際網路的基礎。我們将在需要時指定OSI模型,例如在接下來的章節中讨論Web架構時。

1.3 用戶端–伺服器模型

參考模型示範了資料在兩個節點之間進行通信的标準方法。當然,到目前為止,我們都知道并非所有節點都是相同的。即使在DARPA網絡時代,也有工作站節點,并且有些節點的目的是向其他節點提供内容。這些伺服器節點通常具有更高的硬體規格,并由工程師更密切地管理。由于這些節點向其他節點提供資源和服務,是以通常稱它們為伺服器。伺服器通常處于空閑狀态,等待用戶端發起對其資源的請求。用戶端請求的分布式資源模型稱為用戶端–伺服器模型。

為什麼這很重要?如果你思考一下,用戶端–伺服器模型突出顯示了網絡的重要性。如果沒有它,那麼對網絡互連的需求就沒有那麼大。需要從用戶端向伺服器傳輸位和位元組,這顯示了網絡工程的重要性。當然,我們都知道它們中最大的網絡—網際網路,是如何持續改變我們所有人的生活。

如果你問每個節點在每次互相通信時如何确定時間、速度、來源和目的地,這些問題将涉及接下來的網絡協定。

1.4 網絡協定簇

在計算機網絡的早期階段,協定是專有的,并由設計連接配接方法的公司嚴密控制。如果你在主機中使用Novell的IPX/SPX協定,你就無法與Apple的AppleTalk主機進行通信,反之亦然。這些專有協定簇通常具有與OSI參考模型類似的層,并遵循用戶端–伺服器通信方法。它們通常在封閉的區域網路(LAN)中工作得很好,而不需要與外界通信。當資料流确實需要超出本地LAN時,通常使用網際網路工作裝置(如路由器)将一種協定轉換為另一種協定。比如将AppleTalk網絡連接配接到基于IP的網絡的路由器。這種轉換通常并不完美,但由于在早期大多數通信發生在LAN内,是以沒關系。

然而,随着對網絡間通信的需求超越LAN,标準化網絡協定簇的需求變得更大。專有協定最終被TCP、UDP和IP的标準化協定取代,這大大提高了網絡間通信的能力。網際網路是其中最大的網絡,它依賴于這些協定才能維持正常功能。在接下來的幾節中,我們将介紹每個協定簇。

1.4.1 傳輸控制協定

傳輸控制協定(TCP)是當今網際網路上使用的主要協定之一。如果你打開了一個網頁或發送電子郵件,你就使用了TCP。該協定位于OSI模型的第4層,它負責以可靠的和錯誤檢查的方式在兩個節點之間傳遞資料段。TCP由160位頭部組成,其中包括源端口和目标端口、序列号、确認号、控制标志和校驗和:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.4.1.1 TCP的功能和特點

TCP使用資料報套接字或端口來建立主機到主機的通信。網際網路号碼配置設定委員會(IANA)是為常用的端口指定确定服務的标準機構,例如端口80提供HTTP(Web)服務,端口25提供SMTP(郵件)服務。用戶端–伺服器模型中的伺服器通常監聽這些常用的端口,以便從用戶端接收通信請求。TCP連接配接由作業系統通過表示連接配接的本地端點套接字管理。

協定操作由狀态機組成,其中在通信會話期間,當監聽一個輸入連接配接時機器需要進行跟蹤,并且在連接配接關閉後釋放資源。每個TCP連接配接都經曆一系列狀态,例如Listen、SYN-SENT、SYN-RECEIVED、ESTABLISHED、FIN-WAIT、CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT和CLOSED。

1.4.1.2 TCP消息和資料傳輸

與處于同一層上的使用者資料報協定(UDP)相比TCP最大的差別在于,它以有序和可靠的方式傳輸資料。由于操作保證傳遞,通常稱TCP為面向連接配接的協定。它首先通過建立三次握手來同步發送器和接收器、SYN、SYN-ACK和ACK之間的序列号來實作這一點。

确認用于跟蹤對話中的後續段。最後,在對話結束時,一方将發送FIN消息,另一方将确認FIN消息以及發送自己的FIN消息。然後,FIN發起方将确認它收到的FIN消息。

正如許多解決TCP連接配接故障的人告訴你的那樣,操作會變得非常複雜。可以确定的是,通常這些操作隻是在背景默默地進行。

僅是TCP就可以寫一整本書,事實上,有許多關于協定的優秀的書籍。

警告:由于本節是一個快速概述,如果感興趣,TCP/IP指南(

http://www.tcpipguide.com/

)是一個很好的免費資源,你可以用它來深入研究該主題。

1.4.2 使用者資料報協定

使用者資料報協定(UDP)也是網際網路協定簇的核心成員。與TCP一樣,它位于OSI模型的第4層,該模型負責在應用層和IP層之間傳遞資料段。與TCP不同,UDP頭部僅有64位,僅包含源和目标端口、長度和校驗和。輕量級頭部使其非常适合快速資料傳輸而無須在兩台主機之間設定會話,也不需要可靠資料傳輸。也許今天快速的網際網路連接配接很難想象,但額外的頭部對X.21和幀中繼連結的早期傳輸速度産生了很大的影響。雖然與速度差異一樣重要,但不必維護各種狀态(如TCP),也可以節省兩個端點上的計算機資源:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

你現在可能想知道為什麼UDP在當今時代曾被使用過,鑒于缺乏可靠的傳輸,我們不希望所有連接配接都可靠且無差錯嗎?如果你考慮多媒體視訊流或Skype呼叫,這些應用程式隻想盡快傳送資料報,就需要較輕的頭部。你還可以考慮基于UDP的快速DNS查找過程。當你在浏覽器上鍵入的域名被轉換為計算機可了解的位址時,使用者将受益于輕量級過程,因為這必須在你喜愛的網站向你發送資訊之前發生。

同樣,本節并沒有充分展開UDP這個主題,如果讀者有興趣了解UDP的更多資訊,建議讀者通過各種資源探讨該主題。

1.4.3 網際網路協定

正如網絡工程師告訴你的那樣,他們在網際網路協定(IP)層,這是OSI模型的第3層。IP負責在端節點之間尋址和路由。IP的尋址可能是其最重要的工作。位址空間分為兩部分:網絡部分和主機部分。子網路遮罩用于訓示網絡位址中的哪個部分由網絡組成,哪個部分是主機,方法是将網絡部分與1比對,将主機部分與0比對。IPv4和以後的IPv6都以點分表示法表示位址,例如,192.168.0.1。子網路遮罩可以采用點分表示法(255.255.255.0),也可以考慮網絡位(/24)使用正斜杠表示位數:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

IPv6頭部是IPv4的下一代IP頭部,具有固定部分和各種擴充頭部:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

固定頭部部分中的Next Header字段可以訓示随後攜帶附加資訊的擴充頭部。擴充頭部可以包括路由和段資訊。盡管協定設計者希望從IPv4遷移到IPv6,但今天的網際網路仍然采用IPv4,其中一些服務提供商内部使用IPv6尋址的網絡。

1.4.3.1 IP NAT和安全性

網絡位址轉換(NAT)通常用于将一系列私有IPv4位址轉換為公共路由的IPv4位址。但它也可能意味着IPv4到IPv6之間的轉換,例如在營運商邊緣的網絡内部使用IPv6時,當資料包離開網絡時需要被轉換為IPv4。出于安全原因,有時也使用NAT6到6。

安全性是一個連續的過程,內建了網絡的所有方面,包括自動化和Python。本書旨在使用Python來幫助你管理網絡,安全性将作為本書後續章節的一部分來解決,例如通過telnet使用SSHv2。我們還将研究如何使用Python和其他工具來獲得網絡可視化。

1.4.3.2 IP路由概念

在我看來,IP路由是關于讓兩個端點之間的中間裝置基于IP頭部在端點之間傳輸資料包。對于通過網際網路的所有通信,資料包将周遊各種中間裝置。如上所述,中間裝置包括路由器、交換機、光學裝置和各種其他裝置,這些裝置不在網絡層和傳輸層之外進行檢查。類似在公路旅行中,你從美國加利福尼亞州的聖地亞哥市到華盛頓州的西雅圖市。IP源位址類似于聖地亞哥,目标IP位址可以認為是西雅圖。在你的公路旅行中,你将在許多不同的中間景點停留,如洛杉矶、舊金山和波特蘭,這些可以認為是源和目标之間的路由器和交換機。

為什麼這很重要?在某種程度上,本書是關于管理和優化這些中間裝置的。在跨越多個美式足球場大小的大型資料中心時代,對高效、靈活、可靠和具有成本效益的網絡管理方式的需求成為公司競争的重點。在以後的章節中,我們将深入探讨如何使用Python程式設計來有效地管理網絡。

1.5 Python語言概述

簡而言之,本書旨在通過Python使我們的網絡工程更容易實作。但什麼是Python,為什麼它是許多DevOps工程師選擇的語言?用Python組織執行摘要

https://www.python.org/doc/essays/blurb/

)的話來說:

“Python是一種具有動态語義的解釋型、面向對象的進階程式設計語言。它的進階内置資料結構,結合動态類型和動态綁定,使其對快速應用程式開發以及用作腳本或黏合語言将現有元件連接配接在一起非常有吸引力。Python簡單易學的文法可讀性強,是以降低了程式維護的成本。”

如果你是個程式設計新手,那麼前面提到的面向對象的動态語義對你來說可能并不重要。但我認為大家都會認同,快速的應用程式開發、簡單易學的文法是件好事。Python作為一種解釋語言,意味着不需要編譯過程,是以大大減少了編寫、測試和編輯Python程式的時間。對于簡單腳本,如果腳本失敗,隻需要一個print語句來調試正在進行的操作。使用解釋器還意味着Python可以輕松移植到不同類型的作業系統,例如Windows和Linux,并且在一個作業系統上編寫的Python程式可以在另一個作業系統上使用。

通過将大型程式分解為簡單的可重用對象以及具有函數、子產品和包的其他可重用格式,面向對象的性質鼓勵代碼重用。事實上,所有Python檔案都是可以重用或導入另一個Python程式的子產品。這使得在工程師之間共享程式變得容易,并鼓勵代碼重用。Python也有一個開箱即用的工具,這意味着,對于常見的任務,你無須下載下傳任何其他軟體包。為了在不使代碼過于煩瑣的情況下實作所需功能,在安裝Python解釋器時會安裝一組标準庫。對于正常任務,例如正規表達式、數學函數和JSON解碼,你隻需要import語句,解釋器就會将這些函數移動到你的程式中。這就是Python語言的殺手級功能之一。

最後,Python代碼可以從一個相對較小的腳本開始,隻需幾行代碼,發展成一個完整的系統工程,這對網絡工程師來說非常友善。衆所周知,網絡通常在沒有總體規劃的情況下有機增長。可以随網絡規模的增長而增長的語言非常寶貴。你可能會驚訝地發現,許多尖端公司(使用Python的組織:

https://wiki.python.org/moin/OrganizationsUsingPython

)将一種被許多人認為是腳本語言的語言用于完整的系統工程。

如果你曾經在一個必須在不同的供應商平台(例如Cisco IOS和Juniper Junos)間進行切換的環境中工作過,你就會知道為了實作相同任務在不同文法和慣用法之間切換是多麼痛苦。Python對大型和小型程式足夠靈活,不存在這樣的上下文切換。

在本章的其餘部分,我們将對Python語言進行高層次的介紹,并進行一些複習。如果你已經熟悉基礎知識,請快速浏覽或跳過本章的其餘部分。

1.5.1 Python版本

正如許多讀者已經意識到的那樣,Python在過去幾年裡已經從Python 2發展到Python 3。Python 3于2008年釋出,遺憾的是,Python 3并不向後相容Python 2。在2018年中期編寫本書的第2版時,Python已經基本上轉移到Python 3。最新的Python 2.x版本是2.7,該版本于2010年中期釋出。幸運的是,兩個版本可以在同一台機器上共存。就個人而言,當我在指令提示符下鍵入Python時,我使用Python 2作為我的預設解釋器,當我需要使用Python 3時,我需要鍵入Python 3。有關調用Python解釋器的更多資訊将在下一節中講述,一個在Ubuntu Linux機器上調用Python 2和Python 3的示例如下:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

由于2.7版本已經過時,現在大多數Python架構支援Python 3。Python 3還具有許多優秀的功能,例如在我們需要優化代碼時可以使用異步I/O。除非另有說明,否則本書将使用Python 3作為代碼示例。我們還将嘗試指出Python 2和Python 3應用時的差異。

如果特别的庫或架構更适合Python 2,例如Ansible(請參閱以下資訊),我們将會專門指出使用Python 2。

警告:在撰寫本書時,Ansible 2.5及更高版本支援Python 3。在2.5版本之前,支援Python 3的版本被認為是技術預覽版。鑒于相對較新的可支援性,許多社群子產品仍然尚未遷移到Python 3。有關Ansible和Python 3的更多資訊,請參閱

https://docs.ansible.com/ansible/2.5/dev_guide/developing_python_3.html

1.5.2 作業系統

如前所述,Python是跨平台的。Python程式可以在Windows、Mac和Linux上運作。實際上,當你需要確定跨平台相容性時需要特别小心,例如處理Windows檔案名中反斜杠之間的細微差别。由于本書适用于DevOps、系統和網絡工程師,是以Linux是目标閱聽人的首選平台,尤其是在生産環境中。本書中的代碼将在Linux Ubuntu 16.06 LTS機器上進行測試。我還将盡力確定代碼在Windows和MacOS平台上可同樣運作。

作業系統詳細資訊如下:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.3 運作一個Python程式

Python程式由解釋器執行,這意味着代碼被提供給此解釋器,由底層作業系統執行并顯示結果。目前Python開發社群有幾種不同的解釋器,例如IronPython和Jython。在本書中,我們将使用當今最常用的Python解釋器,即CPython。本書中提到Python時,除非另有說明,否則我們指的都是CPython。

使用Python的一種方法是利用互動式提示。當你想要快速測試一段Python代碼或概念而不編寫整個程式時将會有用。通常隻需鍵入Python關鍵字即可實作:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

提示:在Python 3中,print語句是一個函數,是以,它需要括号。在Python 2中,你可以省略括号。

互動模式是Python最有用的功能之一。在互動式shell中,你可以鍵入任何有效的語句或語句序列,并立即獲得傳回結果。我通常使用這種方法來探索我不熟悉的功能或庫。互動中立即得到滿意結果!

警告:在Windows上,如果沒有收到Python shell提示符,則在系統搜尋路徑中可能沒有這個程式。最新的Windows Python安裝程式提供了一個用于将Python添加到系統路徑的複選框,確定選中這個複選框。或者,你可以通過轉到“環境設定”手動在路徑中添加程式。

但是,運作Python程式的一種更常見的方法是儲存Python檔案,然後通過解釋器運作它。這将使你無須像在互動式shell中那樣一遍又一遍地鍵入相同的語句。Python檔案隻是正常文本檔案,通常以.py擴充名儲存。在* Nix世界中,你還可以在頂部添加shebang(#!)行以指定将用于運作檔案的解釋器。#字元可用于進行注釋,并且不被解釋器執行。檔案helloworld.py具有以下語句:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

這可以按如下方式執行:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.4 Python内置類型

Python有幾種内置于解釋器的标準類型:

  • 空:Null對象。
  • 數值:int、long、float、complex和bool(有True和False值int的子類)。
  • 序列:str、清單、元組和整數清單。
  • 映射:dict。
  • 集合:set和frozenset。

1.5.4.1 空類型

None類型表示沒有值的對象。在未顯式傳回任何内容的函數中傳回None類型。如果調用者未傳入實際值,則None類型也會在函數參數中用于錯誤輸出。

1.5.4.2 數值

Python數字對象基本上是數字。除布爾值外,int、long、float和complex的數值類型都是有符号的,這意味着它們可以是正數或負數。布爾值是整數的子類,它可以是兩個值之一:1表示True,0表示False。其餘的數值類型由它們如何精确地表示數字來區分,例如,int是具有有限範圍的整數,而long是具有無限範圍的整數。浮點數是使用機器上的雙精度表示(64位)的數字。

1.5.4.3 序列

序列是有序的對象集,其索引為非負整數。在本節和接下來的幾節中,我們将使用互動式解釋器來說明不同的類型。請随意在自己的電腦上打字。

有時人們會驚訝于string實際上是一種序列類型。但如果仔細觀察,字元串就是一系列字元放在一起。字元串由單引号、雙引号或三引号括起來。請注意,在以下示例中,引号必須比對,并且三引号允許字元串跨越不同的行:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

另外兩種常用的序列類型是清單和元組。清單是任意對象的序列。可以通過将對象括在方括号中來建立清單。就像字元串一樣,清單由從零開始的非零整數索引。通過引用索引号來檢索清單的值:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

元組類似于清單,通過将值括在括号中來建立。與清單一樣,元組中的值通過引用其索引号來檢索。與清單不同,元組中的值建立後無法修改:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

某些操作對所有序列類型都是通用的,例如通過索引傳回元素以及切片:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章
帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

警告:請記住,索引從0開始。是以,索引1實際上是序列中的第二個元素。

還有一些常用函數可以應用于序列類型,例如檢查元素數量以及最小值和最大值:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

毫無疑問,有各種方法僅适用于字元串。值得注意的是,這些方法不會修改底層字元串資料本身,并始終傳回新字元串。如果要使用新值,則需要捕獲傳回值并将其配置設定給另一個變量:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

以下是清單的一些常用方法。清單是一個非常有用的結構,它将多個項目放在一起并一次疊代一個項目。例如,我們可以制作一個資料中心主幹交換機清單,并通過逐個疊代它們将相同的通路清單應用于所有這些交換機清單。由于清單的值可以在建立後修改(與元組不同),是以當我們繼續執行程式時還可以擴充和對比現有清單:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.4.4 字典

Python提供了一種映射類型,稱為字典。字典包含可以通過鍵索引的對象,這在其他語言中通常被稱為關聯數組或散清單。如果你使用過其他語言中的任何類字典對象,你将會知道這是一種強大的類型,因為你可以使用人類可讀的鍵來引用該對象。對于試圖維護和排除代碼故障的人來說,這個鍵更有意義。字典值中的對象也可以是另一種資料類型,例如清單。你可以使用花括号建立字典:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.4.5 集合

集合用于包含無序的對象集。與清單和元組不同,集合是無序的,不能用數字編制索引。但是集合有一個有用的突出特點:集合的元素絕不會重複。想象一下,你有一個IP清單,你需要将其放入通路清單中。這個IP清單中唯一的問題是裡面有重複值。現在,考慮一下你将使用多少行代碼來周遊IP清單以一次一個地排序唯一項目。但是,内置集合類型允許你隻用一行代碼消除重複的條目。說實話,我不經常使用集合,但是當我需要它時,我總是非常感謝它的存在。建立一個或多個集合後,可以使用并集,交集和差集将它們互相比較:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章
帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.5 Python操作符

Python有一些你期望的數值運算符,值得注意的是截斷除法(//,也稱為floor division)将結果截斷為整數和浮點并傳回整數值。模數(%)運算符傳回除法中的餘數值:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

還有比較運算符。需要注意用于比較的雙等号和用于變量指派的單個等号:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

我們還可以使用兩個公共成員運算符來檢視對象是否在序列類型中:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.6 Python控制流工具

if、else和elif語句控制條件代碼執行。正如人們所預料的那樣,條件語句的格式如下:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

這裡是一個簡單的例子。

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

while循環将繼續執行,直到條件為false,是以如果你不想繼續執行(并使程序崩潰),請小心使用此循環:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

for循環适用于任何支援疊代的對象,這意味着所有内置序列類型(如清單、元組和字元串)都可以在for循環中使用。以下for循環中的字母i是一個疊代變量,是以你通常可以在代碼上下文中擷取有意義的内容:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章
帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

你還可以建立自己的支援疊代器協定的對象,并能夠為此對象使用for循環。

建構這樣一個對象超出了本章的範圍,但這是有用的知識,你可以在

https://docs.python.org/3/c-api/iter.html

閱讀更多相關資訊。

1.5.7 Python函數

大多數情況下,當你發現自己複制并粘貼一些代碼時,你應該把它分解成一個自包含的功能塊。這種做法允許更好的子產品化,更易于維護,并允許代碼重用。Python函數使用帶有函數名稱的def關鍵字定義,後邊跟着函數參數。函數體由要執行的Python語句組成。在函數結束時,你可以選擇将值傳回給函數調用者,或者預設情況下,如果你沒有指定傳回值,它将傳回None對象:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

我們将在後面的章節中看到更多的函數示例,是以這裡有一個簡單的例子:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

1.5.8 Python類

Python是一種面向對象程式設計(OOP)語言。Python建立對象的方式是使用class關鍵字。Python對象通常是函數(方法)、變量和屬性的集合。定義一個類後,你可以建立此類的執行個體。該類充當後續執行個體的藍圖。

OOP的主題超出了本章的範圍,是以這裡有一個router對象定義的簡單示例:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章
帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

一旦類定義後,你就可以根據需要建立該類的任意數量的執行個體:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

當然,Python對象和OOP還有很多内容。我們将在以後的章節中檢視更多示例。

1.5.9 Python子產品和包

任何Python源檔案都可以用作子產品,你可以重用在該源檔案中定義的任何函數和類。要加載代碼,引用子產品的檔案需要使用import關鍵字。導入檔案時會發生三件事:

  1. 該檔案為源檔案中定義的對象建立新的命名空間。
  2. 調用者執行子產品中包含的所有代碼。
  3. 該檔案在調用者中建立一個名稱,該名稱引用正在導入的子產品。該名稱與子產品的名稱比對。

    還記得使用互動式shell定義的subtract()函數嗎?要重用該函數,我們可以将它放入名為subtract.py的檔案中:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

在subtract.py的同一目錄下的檔案中,你可以啟動Python解釋器并導入此函數:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

這是有效的,因為預設情況下,Python将首先搜尋可用子產品的目前目錄。如果你位于其他目錄中,則可以使用帶有sys.path的sys子產品手動添加搜尋路徑位置。還記得我們前面提到的标準庫嗎?你猜對了,那些隻是用作子產品的Python檔案。

包允許将子產品集合組合在一起。這進一步将Python子產品組織為更多命名空間保護,以進一步提高可重用性。通過建立具有要用作命名空間的名稱的目錄來定義包,然後可以将子產品源檔案放在該目錄下。為了讓Python将其識别為Python包,隻需在此目錄中建立一個__init__.py檔案即可。在與subtract.py檔案相同的示例中,如果要建立名為math_stuff的目錄并建立__init__.py檔案:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

你現在引用該子產品的方式将需要包含包名稱:

帶你讀《Python網絡程式設計(原書第2版)》之一:回顧TCP/IP協定簇和Python第1章

如你所見,子產品和包是組織大型代碼檔案和使Python代碼共享更加容易的好方法。

1.6 小結

在本章中,我們介紹了OSI模型并回顧了網絡協定簇,例如TCP、UDP和IP。它們用作處理任意兩台主機之間的尋址和通信協商的層。這些協定在設計時考慮了可擴充性,并且與其原始設計基本保持不變。考慮到網際網路的爆炸性增長,這是一個相當大的成就。

我們還快速回顧了Python語言,包括内置類型、運算符、控制流、函數、類、子產品和包。Python是一種功能強大的用于生産環境的語言,易于閱讀。這使得該語言成為網絡自動化的理想選擇。網絡工程師可以利用Python從簡單的腳本開始,逐漸轉向其他進階功能。

在第2章中,我們将開始研究如何使用Python以程式設計方式與網絡裝置進行互動。