首先,來看一個代碼,使用TCP協議,發送端發送一句話,接收端接收並顯示,運行完全正常。
接下來,把客戶端代碼稍微修改一下,連續發送多個數據,
按照正常的想法,在服務端輸出的信息應該是分爲多行的,這樣才和客戶端對應。然後運行結果並不是想象的那樣子。從運行結果來看,應該是服務端把收到的數據放在緩衝區裏了,有了足夠多的數據之後才處理。
recv()方法的參數用來確定一次從緩衝區中最多讀取多少字節的數據,爲了清楚其含義,稍微修改代碼,
學過計算機網絡的朋友一般會聽說過Nagle算法。在使用TCP協議進行傳輸時,會在有效數據前面增加大量頭部信息來保證可靠傳輸,如果發送的有效數據非常短,增加頭部帶來的額外開銷就非常大。爲了優化和減少帶寬佔用,避免大量小包堵塞網絡,發送端會在發送大量小包時積累一定數量的數據之後組成一個大包晚些時間再發送(粘包),在發送大包時會根據情況切分成多個包發送(斷包)。同理,接收端在接收大包時有可能會進行截斷以免緩衝區放不下(斷包),接收連續多個小包時會在緩衝區暫存一段時間合併成大包再處理(粘包),也就是所謂Nagle算法。
Nagle算法的優化在大部分情況下都是非常好的,但也會給接收端帶來一定的麻煩,必須要正確識別和讀取一個完整的包之後再處理,以免後面的功能代碼無法正常工作。這需要額外寫更多代碼來正確讀取一個完整的包,例如發送端先告知接收端要發送的數據長度,或者雙方約定好數據的起始標記和結束標記。
如果到網上(甚至一些書上)搜索資料,會說禁用Nagle算法就可以了,也就是設置套接字屬性啓用TCP_NODELAY,非常簡單。既然如此,那就趕緊用起來吧。
在Python中,標準庫socket封裝了套接字編程需要的功能,創建套接字之後可以使用setsockopt來設置當前套接字的各種屬性,其中就包括禁用斷包和粘包的延遲從而禁用Nagle算法。
結果顯示,這個選項根本沒有起作用。那會不會是需要在通信雙方都啓用TCP_NODELAY呢?於是把客戶端也設置一下,重新運行程序,發現還是沒有用。
繼續查資料,會有人說,要真正禁用Nagle算法只把TCP_NODELAY設置爲True是不夠的,還需要把接收端的接收緩衝區大小設置爲0纔行。原來是這樣啊,那就趕緊修改代碼吧,事實證明還是沒有用的。
也有資料顯示,通信雙方需要協商一下,爲避免接收端粘包時誤把下一條信息的一部分合併到當前信息尾部,可以協商一個起始標記和結束標記,接收端根據接收的信息來查找這些標記並進行正確的切分。這聽起來是個好思路,但真正用起來的時候難度還是很大的,感興趣的朋友可以嘗試一下。
再一個思路也是在傳輸大量數據時經常使用的,就是發送端首先告訴對方接下來要發送的數據長度,然後再發送實際數據。接收端首先接收一個整數來表示接下來要接收的數據總長度,然後使用循環來接收數據,直到恰好接收完剛纔約定的數據長度爲止。爲了避免發生粘包,接收端需要動態調整緩衝區大小來控制每次接收的數據,防止接收多了。
現在的問題就是如何確保把數據長度有效傳遞給對方了,可以使用Python標準庫struct把整數序列化爲字節串發送給對方,而這個字節串的長度固定爲4,這樣的話,接收端使用recv(4)接收到這個字節串再反序列化爲整數就可以了。
上面這個思路是完美的,也是優先推薦使用的,但是需要在編寫程序之前就確定好代碼思路和框架。
如果在編寫代碼時沒有遵循這個思路,都是直接進行發送和接收導致了粘包的發生,又不想對代碼進行大幅度的修改,可以考慮在發送完一段完整意義的數據之後加一個很小的延時,這樣接收端不會等待更多數據後一起處理。雖然這樣可以實現功能,但這個小延時的積累是非常大的,非常不適合服務端代碼的設計,要慎重使用。
在本文最後,給出一個多線程版本的Socket程序,供參考。
溫馨提示
關注本公衆號“Python小屋”,通過菜單“最新資源”==>“歷史文章”可以快速查看分專題的1000篇技術文章列表(可根據關鍵字在頁面上搜索感興趣的文章),通過“最新資源”==>“微課專區”可以免費觀看500節Python微課,通過“最新資源”==>“培訓動態”可以查看近期Python培訓安排,通過“最新資源”==>“教學資源”可以查看Python教學資源。
---董付國老師Python系列圖書---
友情提示:不建議購買太多,最好先通過京東、噹噹、天貓查閱圖書瞭解目錄和側重點,然後再選擇購買適合自己的書。
(1)《Python程序設計(第2版)》(ISBN:978-7-302-43651-5),清華大學出版社,2016年8月出版,2019年度清華大學出版社暢銷圖書
(2)《Python可以這樣學》(ISBN:978-7-302-45646-9),清華大學出版社,2017年2月
(3)《Python程序設計基礎(第2版)》(ISBN:978-7-302-49056-2)清華大學出版社,2018年1月出版,2019年度清華大學出版社暢銷圖書
(4)《中學生可以這樣學Python》(ISBN:978-7-302-48039-6)清華大學出版社
(5)《Python程序設計開發寶典》(ISBN:978-7-302-47210-0)清華大學出版社,2018年10月
(6)《玩轉Python輕鬆過二級》(ISBN:978-7-302-49916-9)清華大學出版社,2018年5月
(7)《Python程序設計基礎與應用》(ISBN:978-7-111-60617-8),機械工業出版社,2018年9月
(8)《Python程序設計實驗指導書》(ISBN:9787302525790),清華大學出版社,2019年4月
(9)《Python編程基礎與案例集錦(中學版)》(ISBN:978-7-121-35539-4),電子工業出版社,2019年4月
(10)《大數據的Python基礎》(ISBN:978-7-111-62455-4),機械工業出版社,預計2019年5月出版
(11)譯作《Python程序設計》,機械工業出版社(華章),2018年11月出版
(12)繁體版《Python也可以這樣學》,臺灣博碩文化股份有限公司,2017年10月出版,本書爲《Python可以這樣學》在臺灣發行的繁體版,兩本書內容一樣,不建議重複購買。
(13)《Python程序設計實例教程》(ISBN:978-7-111-63198-9),機械工業出版社
(14)《Python數據分析、挖掘與可視化》(ISBN:978-7-115-52361-7),人民郵電出版社,2019年12月
《Python數據分析、挖掘與可視化》前3章書稿PDF免費閱讀
相關閱讀
Python+winreg+netifaces查看網絡接口信息
Python+socket+多線程實現同時應答多客戶端的自助聊天機器人
Python版課堂管理系統中使用UDP廣播遠程關閉客戶端程序思路與源碼