上一篇說(shuō)recv()問(wèn)題,我描述錯(cuò)誤了,很多網(wǎng)友一眼就發(fā)現(xiàn)了,而且指了出來(lái),十分感謝。
更難得的是第4位回復(fù)者,不但發(fā)現(xiàn)我的錯(cuò)誤,而且能推測(cè)出我實(shí)現(xiàn)中是怎么做的,這種分析能力,一方面體現(xiàn)出你一定的實(shí)際開(kāi)發(fā)經(jīng)驗(yàn),另一方面也體現(xiàn)了你對(duì)需求理解能力一定很不錯(cuò)。
正如第4位回復(fù)者所說(shuō),為了能方便使用經(jīng)典的同步-阻塞模式,一般會(huì)采用select()-recv()搭配調(diào)用,還會(huì)對(duì)recv()進(jìn)行封裝.
ssize_t recv(int s, void *buf, size_t len, int flags);
其行為是有數(shù)據(jù)就返回,返回實(shí)際收到長(zhǎng)度: [1, len], 或者正常關(guān)閉返回0, 或者出現(xiàn)錯(cuò)誤返回-1.
因?yàn)槲覀儜?yīng)用常常喜歡使用包頭固定長(zhǎng)度 + 包體變長(zhǎng)模式來(lái)處理,我們是知道我們一定要多長(zhǎng)才能正確得到一個(gè)協(xié)議包的,所以收滿一個(gè)固定包頭長(zhǎng)度才能處理,得到包體長(zhǎng)度值,再用這個(gè)長(zhǎng)度去接收包體。
因此做一個(gè)封裝是常見(jiàn)現(xiàn)象:
bool Read(int sock, char * buffer, size_t len)
{
int ret = 0;
while( len > 0 ) {
ret = recv( sock, buffer, len, 0 );
if( 0 >= ret ) {
return false;
}
buffer += ret;
len -= ret;
}
return true;
}
這個(gè)其實(shí)也不完全是現(xiàn)實(shí)中的,現(xiàn)實(shí)中可能返回int, 可能里面有日志處理,可能直接有close()。
總之,這么封裝之后,你調(diào)用Read( buf, 31), 如果服務(wù)器只返回4個(gè)字節(jié),既不關(guān)閉也不異常,那結(jié)果就是一直等待數(shù)據(jù)到來(lái)。
If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is non-blocking。
歡迎多討論,歡迎多發(fā)現(xiàn)問(wèn)題。