爲什麼send()
在winsock
保證傳送您請求的所有字節?send()不傳遞所有字節?
這是TCP,它是阻塞套接字。
同樣,這種情況發生在非阻塞時。你怎麼能保證你發送的一切?
我注意到recv()
也是這麼做的。
爲什麼send()
在winsock
保證傳送您請求的所有字節?send()不傳遞所有字節?
這是TCP,它是阻塞套接字。
同樣,這種情況發生在非阻塞時。你怎麼能保證你發送的一切?
我注意到recv()
也是這麼做的。
如果它沒有發送任何東西,請在其餘的地方再次調用send
。如果阻塞,您可以立即執行。如果非阻塞,您可以等待或使用套接字發現方法(如select
或I/O完成端口)。 recv
也是如此。如果你沒有得到你想要的,請再次致電recv
。這是recv
和send
返回發送或接收的字節數的原因之一。
您傳遞給send
或recv
的字節數只是一個限制。它可以發送比這更少的(儘管,除非非阻塞,通常不會)。但它肯定會收到比這少的。 (操作系統無法控制接收的數據量或收到的數據量。)
TCP是爲您實施的。但是如果你有一個涉及應用程序級消息的應用程序協議,那麼應用程序必須實現它們。它不會發生魔法。 TCP不會「將字節粘合在一起」成爲一條消息。 TCP是一種字節流協議,不是消息協議。如果你想要消息,你必須實現它們。
send
告訴你它能夠通過它的返回值發送什麼。 循環直到send
累積發送所有數據或返回錯誤。
此行爲是「按設計」。
您可以使用外循環,如圖所示:
int sendBuffer (SOCKET ClientSocket, const char *buf, int len, int flags)
{
int num_left = len;
int num_sent;
int err = 0;
const char *cp = buf;
while (num_left > 0)
{
num_sent = send(ClientSocket, cp, num_left, flags);
if (num_sent < 0)
{
err = SOCKET_ERROR;
break;
}
assert(num_sent <= num_left);
num_left -= num_sent;
cp += num_sent;
}
return (err == SOCKET_ERROR ? SOCKET_ERROR : len);
}
發送的0個字節並不表示連接已終止。 –
@LittleHelper:是的,你說得對!糾正。 –
大衛,稍OT但沒有我們comp.protocols.tcp-IP幾年前討論,實際上它併發送/緩衝阻塞模式下的所有字節?在所有已知的平臺上? – EJP
@EJP:對於TCP,除非被信號中斷或發生錯誤,否則我所知道的每個實現都至少會將您在阻塞模式下傳遞給'send'的所有字節排隊,並且不會返回少於您請求的字節數它發送。 (這並不意味着一個實現不會在下週推出,但是可能很多現有代碼會在該實現中斷裂。) –