總會看到c++新手寫網絡通訊時,不理解recv()為什么阻塞或不阻塞,TCP數據順序會不會亂,UDP會不會數據包不完整,都是對TCP/IP協議原理沒有基本常識導致的。
我曾看到代碼,客戶端recv(buf, 31), 實際服務器只會發送4個字節,客戶端將永遠阻塞,直到服務器主動close()為止。
開始時那個服務器是實現一請求一應答,答應后立即關閉,所以客戶端沒有事。
后來服務器維護者,感覺要支持一個連接上支持一個或多個請求,就修改成等待客戶端自己關閉或網絡異常,服務器才關閉socket。這個修改看來是正常的,因為服務器一般寫法都是被動關閉的,關閉權在客戶端。可是這么一修改,原來那個客戶端就阻塞死了,用戶莫名其妙。
這里有一個有趣現象:如果服務器維護者不修改,那么那個客戶端軟件一直是可以正常運行的,但從我們開發者角度來看,明明是一種實現錯誤,至少是缺陷吧。可是,測試人員黑盒測試是不可能測試出來的,一般測試人員也不會去寫代碼測試,所以這種問題測試組搞不定。
很多時候,在測試環境里沒問題,在真實環境就出現一些古怪的問題,其實問題不古怪。
比如:A通過TCP向B發送1024字節,B采用一次性接收recv(buf, 1024), 測試環境常常每次都是一次收滿,包是完整的;在真實環境,A和B在不同地域,之間不知道多少交換機和路由器,那可能就第一次只收到500字節,如果不加判斷返回值亂處理,問題就出來了。
這個問題還不止一次看到新手這么干。