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