這與TCP接收完全不同,TCP沒有完整包的概念,也沒有邊界,OS只會取出用戶要求的大小,剩余的仍然保留在OS中,下次還可以繼續取出。
socket編程雖然是事實上的標準,而且不同平臺提供的接口函數也非常類似,但畢竟它不存在嚴格的標準。所以各個平臺的實現也不完全兼容。下面就從recvfrom()這個函數看看Window平臺和Linux平臺的不同。
Windows平臺的表現
int
WSAAPI
recvfrom(
_In_ SOCKET s,
_Out_writes_bytes_to_(len, return) __out_data_source(NETWORK) char FAR * buf,
_In_ int len,
_In_ int flags,
_Out_writes_bytes_to_opt_(*fromlen, *fromlen) struct sockaddr FAR * from,
_Inout_opt_ int FAR * fromlen
);
再看MSDN說明:
If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost.
可以看出,buf大小小於UDP包大小的時候,recvfrom()會返回-1,並設置錯誤WSAEMSGSIZE。
實際編程測試驗證確實是這樣的表現。
Linux平臺的表現
__extern_always_inline ssize_t
recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
__SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)
可以看出與Windows平臺的函數原型相同。但是在其man手冊裏,沒有看到UDP包大於接收緩沖區情況的特殊說明。
寫代碼測試表明,buf小於UDP包大小的時候,recvfrom()仍然返回復制到緩沖區的字節數,調用者無法得知UDP包被截斷的情況。