這里必須要手動去設置,用的就是cmd,widows自帶的命令開wifi。
B. 怎麼樣才能提高python程序的網路吞吐速率
Python是一個很酷的語言,因為你可以在很短的時間內利用很少的代碼做很多事情。不僅如此,它還能輕松地支持多任務,比如多進程等。Python批評者有時會說Python執行緩慢。本文將嘗試介紹6個技巧,可加速你的Python應用程序。
1.讓關鍵代碼依賴於外部包
雖然Python讓許多編程任務變得容易,但它可能並不總能為緊急的任務提供最佳性能。你可以為緊急的任務使用C、C++或機器語言編寫的外部包,這樣可以提高應用程序的性能。這些包都是不能跨平台的,這意味著你需要根據你正在使用的平台,尋找合適的包。簡而言之,這個方案放棄了一些應用程序的可移植性,以換取只有在特定主機上直接編程才能獲得的程序性能。這里有一些你應該考慮加入到你的「性能兵工廠」的包:
Cython
PyInlne
PyPy
Pyrex
這些包以不同的方式提高性能。例如,Pyrex能夠擴展Python所能做的事情,例如使用C的數據類型來讓內存任務更加有效或直接。PyInIne讓你在Python應用程序中直接使用C代碼。程序中的內聯代碼單獨編譯,但它在利用C語言所能提供的效率的同時,也讓所有的代碼都在同一個地方。
2.排序時使用鍵(key)
有很多老的Python排序代碼,它們在你創建一個自定義的排序時花費你的時間,但在運行時確實能加速執行排序過程。元素排序的最好方法是盡可能使用鍵(key)和默認的sort()排序方法。例如,考慮下面的代碼:
每一個實例中,根據你選擇的作為key參數部分的索引,數組進行了排序。類似於利用數字進行排序,這種方法同樣適用於利用字元串排序。
3.優化循環
每種編程語言都會強調需要優化循環。當使用Python的時候,你可以依靠大量的技巧使得循環運行得更快。然而,開發者經常漏掉的一個方法是:避免在一個循環中使用點操作。例如,考慮下面的代碼:
每一次你調用方法str.upper,Python都會求該方法的值。然而,如果你用一個變數代替求得的值,值就變成了已知的,Python就可以更快地執行任務。優化循環的關鍵,是要減少Python在循環內部執行的工作量,因為Python原生的解釋器在那種情況下,真的會減緩執行的速度。
(注意:優化循環的方法有很多,這只是其中的一個。例如,許多程序員都會說,列表推導是在循環中提高執行速度的最好方式。這里的關鍵是,優化循環是程序取得更高的執行速度的更好方式之一。)
4.使用較新版本的Python
在網上搜索Python信息,都會發現無數人在問,從Python一個版本遷移到另一個版本的問題的信息。一般來說,Python的每一個版本都包含了能讓其比上個版本運行更快的優化。版本遷移的限制因素是,你喜歡的那些庫是否已經遷移到Python的較新版本。相比於詢問是否應該進行版本遷移,關鍵問題是確定一個新版本什麼時候有足夠的支持,以保證遷移的可行性。
你需要驗證你的代碼仍然運行。你需要在Python的新版本下使用你獲得的新庫,然後檢查你的應用程序是否需要重大改變。只有在你作出必要的更正之後,你才會注意到版本之間的差別。然而,如果你正好確保你的應用程序能在新版本下運行,而不需要任何改變,你可能會錯過那些版本升級帶來的新特性。一旦你進行了遷移,你應該為你的新版本下的應用程序寫一個說明,檢查有問題的地方,並且優先考慮利用新版本的特性去更新那些地方。這樣用戶將會在升級的過程中更早的看到一個更大的性能提升。
5.嘗試多種編碼方法
如果每次你創建一個應用程序都是用相同的編碼方法,幾乎肯定會導致一些你的應用程序比它能夠達到的運行效率慢的情況。作為分析過程的一部分,你可以嘗試一些實驗。例如,在一個字典中管理一些元素,你可以採用安全的方法確定元素是否已經存在並更新,或者你可以直接添加元素,然後作為異常處理該元素不存在情況。考慮第一個編碼的例子:
這段代碼通常會在myDict開始為空時運行得更快。然而,當mydict通常被數據填充(或者至少大部分被充填)時,另一種方法效果更好。
兩種情況下具有相同的輸出:{『d': 4, 『c': 4, 『b': 4, 『a': 4}。唯一的不同是這個輸出是如何得到的。跳出固定的思維模式,創造新的編碼技巧,能夠幫助你利用你的應用程序獲得更快的結果。
6.交叉編譯應用程序
開發者有時會忘記,電腦實際上是不懂任何用於創建現代應用程序的語言,電腦所能懂得是機器代碼。為了能在電腦上運行應用程序,你使用一個應用將人類可讀的代碼你轉換成計算機能理解的。有時候用一種語言,比如Python,寫一個應用,並用另一種語言,比如C++,運行它,從性能的角度來看是有意義的。這取決於你想要應用程序去做什麼,以及主機系統可以提供的資源。
一個有趣的交叉編譯器,Nuitka,可以將你的Python代碼轉換為C++代碼。這么做的結果是,你可以在原生模式下執行應用程序,而不是依靠解釋器。根據平台和任務,你可以看到一個顯著的性能提升。
(注意:Nuitka目前還處於測試階段,所以用它來產品程序時需要小心。實際上,目前最好將其用於實驗。現在也有一些關於交叉編譯是否是得到更好性能的最佳方式的討論。開發者已經利用交叉編譯好幾年了,目的是實現特定的目標,比如更好的應用程序的速度。記住,每一個解決方案都會有得有失,你應該在將一個解決方案用於生產環境之前就好好考慮一下得失情況。)
在使用一個交叉編譯器時,要確保它支持你使用的Python的版本。Nuitka支持Python2.6、2.7、3.2和3.3。想讓這個方案發揮作用,你需要一個Python解釋器和一個C++編譯器。Nuitka支持多種C++編譯器,包括Microsoft Visual Studio、MinGW 和 Clang/LLVM。
交叉編譯也可能帶來一些嚴重的負面影響。例如,當利用Nuitka工作時,你會發現即使一個小程序也能消耗很大的硬碟空間,這是因為Nuitka使用大量的動態鏈接庫(DLLs)實現Python的功能。所以當你面對一個資源有限的系統時,這個方案可能不會很好的起作用。
總結
這六個技巧中的任意一個,都可以幫助你創造更快的Python程序。但任何技巧都不是萬能的,不能每次都起作用。有些技巧在Python的特定版本下比其他技巧的更有效——甚至系統平台也能影響它們的效果。你需要配置你的應用,確定哪個地方讓其運行緩慢,然後嘗試似乎能最好的解決這些問題的一些技巧。
C. Python網路編程 -- TCP/IP
首先放出一個 TCP/IP 的程序,這里是單線程伺服器與客戶端,在多線程一節會放上多線程的TCP/IP服務程序沖戚拍。
這里將服務端和客戶端放到同一個程序當中,方便對比服務端與客戶端的不同。
TCP/IP是網際網路的通信協議,其參考OSI模型,也採用了分層的方式,對每一層制定了相應的標准。
網際協議(IP)是為全世界通過互聯網連接的計算機賦予統一地址系統的機制,它使得數據包能夠從互聯網的一端發送至另一端,如 130.207.244.244,為了便於記憶,常用主機名代替IP地址,例如 .com。
UDP (User Datagram Protocol,用戶數據報協議) 解決了上述第一個問題,通過埠號來實現了多路復用(用不同的埠區分不同的應用程序)但是使用UDP協議的網路程序需要自己處理丟包、重包和包的亂序問題。
TCP (Transmission Control Protocol,傳輸控制協議) 解決了上述兩個問題,同樣使用埠號實現了復用。
TCP 實現可靠連接的方法:
socket通信模型及 TCP 通信過程如下兩張圖。
[圖片上傳失敗...(image-6d947d-1610703914730)]
[圖片上傳失敗...(image-30b472-1610703914730)]
socket.getaddrinfo(host, port, family, socktype, proto, flags)
返回: [(family, socktype, proto, cannonname, sockaddr), ] 由元組組成的列表散羨。
family:表示socket使用的協議簇, AF_UNIX : 1, AF_INET: 2, AF_INET6 : 10。 0 表示不指定。
socktype: socket 的類型, SOCK_STREAM : 1, SOCK_DGRAM : 2, SOCK_RAW : 3
proto: 協議, 套接字所用的協議,如果不指定, 則為 0。 IPPROTO_TCP : 6, IPPRTOTO_UDP : 17
flags:標記,限制返回內容。 AI_ADDRCONFIG 把計算機無法連接的所有地址都過濾掉(如果一個機構既有IPv4,又有IPv6,而主機只有IPv4,則會把 IPv6過濾掉)
AI _V4MAPPED, 如果本機只有IPv6,服務卻只有IPv4,這個標記會將 IPv4地址重新編碼為可實際使用的IPv6地址。
AI_CANONNAME,返回規范主機名:cannonname。
getaddrinfo(None, 'smtp', 0, socket.SOCK_STREAM, 0, socket.AP_PASSIVE)
getaddrinfo('ftp.kernel.org', 'ftp', 0, 'socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)
利用已經通信的套接字名提供給getaddrinfo
mysock = server_sock.accept()
addr, port = mysock.getpeername()
getaddrinfo(addr, port, mysock.family, mysock.type, mysock.proto, socket.AI_CANONNAME)
TCP 數據發送模式:
由於 TCP 是發送流式數據,並且會自動分割發送的數據包,而仔槐且在 recv 的時候會阻塞進程,直到接收到數據為止,因此會出現死鎖現象,及通信雙方都在等待接收數據導致無法響應,或者都在發送數據導致緩存區溢出。所以就有了封幀(framing)的問題,即如何分割消息,使得接收方能夠識別消息的開始與結束。
關於封幀,需要考慮的問題是, 接收方何時最終停止調用recv才是安全的?整個消息或數據何時才能完整無缺的傳達?何時才能將接收到的消息作為一個整體來解析或處理。
適用UDP的場景:
由於TCP每次連接與斷開都需要有三次握手,若有大量連接,則會產生大量的開銷,在客戶端與伺服器之間不存在長時間連接的情況下,適用UDP更為合適,尤其是客戶端太多的時候。
第二種情況: 當丟包現象發生時,如果應用程序有比簡單地重傳數據聰明得多的方法的話,那麼就不適用TCP了。例如,如果正在進行音頻通話,如果有1s的數據由於丟包而丟失了,那麼只是簡單地不斷重新發送這1s的數據直至其成功傳達是無濟於事的。反之,客戶端應該從傳達的數據包中任意選擇一些組合成一段音頻(為了解決這一問題,一個智能的音頻協議會用前一段音頻的高度壓縮版本作為數據包的開始部分,同樣將其後繼音頻壓縮,作為數據包的結束部分),然後繼續進行後續操作,就好像沒有發生丟包一樣。如果使用TCP,那麼這是不可能的,因為TCP會固執地重傳丟失的信息,即使這些信息早已過時無用也不例外。UDP數據報通常是互聯網實時多媒體流的基礎。
參考資料:
D. Python網路編程6-使用Pysnmp實現簡單網管
簡單網路管理協議SNMP(Simple Network Management Protocol)用於網路設備的管理。SNMP作為廣泛應用於TCP/IP網路的網路管理標准協議,提供了統一的介面,從而實現了不同種類和廠商的網路設備之間的統一管理。
SNMP協議分為三個版本:SNMPv1、SNMPv2c和SNMPv3。
SNMP系統由網路管理系統NMS(Network Management System)、SNMP Agent、被管對象Management object和管理信息庫MIB(Management Information Base)四部分組成。
SNMP查詢是指NMS主動向SNMP Agent發送查詢請求,如圖1-3所示。SNMP Agent接收到查詢請求後,通過MIB表完成相應指令,並將結果反饋給NMS。SNMP查詢操作有三種:Get、GetNext和GetBulk。SNMPv1版本不支持GetBulk操作。
不同版本的SNMP查詢操作的工作原理基本一致,唯一的區別是SNMPv3版本增加了身份驗證和加密處理。下面以SNMPv2c版本的Get操作為例介紹SNMP查詢操作的工作原理。假定NMS想要獲取被管理設備MIB節點sysContact的值,使用可讀團體名為public,過程如下所示:
SNMP設置是指NMS主動向SNMP Agent發送對設備進行Set操作的請求,如下圖示。SNMP Agent接收到Set請求後,通過MIB表完成相應指令,並將結果反饋給NMS。
不同版本的SNMP Set操作的工作原理基本一致,唯一的區別是SNMPv3版本增加了身份驗證和加密處理。下面以SNMPv3版本的Set操作為例介紹SNMP Set操作的工作原理。
假定NMS想要設置被管理設備MIB節點sysName的值為HUAWEI,過程如下所示:
SNMPv1和SNMPv2c的Set操作報文格式如下圖所示。一般情況下,SNMPv3的Set操作信息是經過加密封裝在SNMP PDU中,其格式與SNMPv2c的Set操作報文格式一致。
SNMP Traps是指SNMP Agent主動將設備產生的告警或事件上報給NMS,以便網路管理員及時了解設備當前運行的狀態。
SNMP Agent上報SNMP Traps有兩種方式:Trap和Inform。SNMPv1版本不支持Inform。Trap和Inform的區別在於,SNMP Agent通過Inform向NMS發送告警或事件後,NMS需要回復InformResponse進行確認。
在Ensp中搭建網路環境,在R2上啟用SNMP作為SNMP agent,Linux主機作為NMS;為方便觀察SNMP報文格式,在R2使用SNMP的版本為v2c。
通過下面的Python腳本獲取R2的系統信息與當前的主機名
運行結果如下
在R2介面上抓包結果如下,Linux主機向R2的161埠發送SNMP get-request報文,可以看到SNMP使用的版本為v2c,設置的團體名為public,隨機生成了一個request-id,變數綁定列表(Variable bindings),即要查詢的OID,但Value為空;值得注意的是這些信息都是明文傳輸的,為了安全在實際環境中應使用SNMPv3。
通過下面的Python腳本獲取R2的介面信息。
運行結果如下:
在R2介面抓包結果如下,getBuikRequest相比get-request設置了一個max-repetitions欄位,表明最多執行get操作的次數。Variable bindings中請求的OID條目只有一條。
下面Python腳本用於設置R2的主機名為SNMPv2R2。
運行結果如下
在路由器上可以看到主機名有R2變為了SNMPv2R2。
get-response數據包內容與set-request中無異。
下面Python腳本用於接收,R2發送的Trap,並做簡單解析。
先運行該腳本,之後再R2上手動將一個介面shutdown,結果如下:
介面上抓包結果如下,此時團體名用的是public,data部分表明是trap。
由於Ensp中的通用路由器認證演算法只支持des56,而pysnmp不支持該演算法,因此使用AR路由器配置SNMPv3。
使用下面Python腳本發送snmpv3 get報文獲取設備系統信息。
抓包結果如下,首先發送get-resques進行SNMPv3認證請求,隨機生成一個msgID,認證模式為USM,msgflgs中Reportable置1要求對方發送report,其他為置0,表示不進行加密與鑒權;另外安全參數,認證參數、加密參數都為空,此時不攜帶get請求數據。
路由器給NMS回復report,msgID與resquest一致,Msgflgs中各位都置0,同時回復使用的安全引擎,認證與加密參數為空,不進行認證與加密,因此能看到data中的數據。
AR1收到請求後進行回復,數據包中msgflags標志位中除reportable外其他位都置1,表示不需要回復,同時進行加密與鑒權。同樣也可以看到認證用戶為testuser,認證參數與加密參數都有填充,data部分也是同樣加密。
參考:
什麼是SNMP - 華為 (huawei.com)
AR100-S V300R003 MIB參考 - 華為 (huawei.com)
SNMP library for Python — SNMP library for Python 4.4 documentation (pysnmp.readthedocs.io)