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