在使用TCP編寫的應(yīng)用程序和使用UDP編寫的應(yīng)用程序之間存在一些本質(zhì)差異,其原因在于這兩個(gè)傳輸層之間的差別:UDP是無(wú)連接不可靠的數(shù)據(jù)報(bào)協(xié)議,非常不同于TCP提供的面向連接的可靠字節(jié)流。然而相比TCP,有些場(chǎng)合確實(shí)更適合使用UDP。使用UDP編寫的一些常見(jiàn)的應(yīng)用程序有:NDS域名系統(tǒng)、NFS網(wǎng)絡(luò)文件系統(tǒng)和SNMP簡(jiǎn)單網(wǎng)絡(luò)管理協(xié)議。
下圖給出了典型的UDP客戶/服務(wù)器程序的函數(shù)調(diào)用。客戶不與服務(wù)器建立連接,而是只管使用sendto函數(shù)給服務(wù)器發(fā)送數(shù)據(jù)報(bào),其中必須指定目的地的地址作為參數(shù)。類似的,服務(wù)器不接受來(lái)自客戶的連接,而是只管調(diào)用recvfrom函數(shù),等待來(lái)自某個(gè)客戶的數(shù)據(jù)到達(dá)。recvfrom函數(shù)將與所接收的數(shù)據(jù)報(bào)一道返回客戶的協(xié)議地址。因此服務(wù)器可以把響應(yīng)發(fā)送給正確的客戶。

recvfrom和sendto函數(shù)
這兩個(gè)函數(shù)類似于標(biāo)準(zhǔn)的read和write函數(shù),不過(guò)需要三個(gè)額外的參數(shù)。
#include <sys/socket.h>
ssize_t??recvfrom(int? sockfd,? void*??buff , size_t?? nbytes , int?? flags , struct? sockaddr*?from , socklen_t*? addrlen);
ssize_t??sendto(int? sockfd,? const?void*? buff, size_t? nbytes, int?flags, const? struct? sockaddr* to, socklent_t? addrlen);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?返回: 若成功則為讀或者寫的字節(jié)數(shù),若出錯(cuò)則為-1
前三個(gè)參數(shù)sockfd、buff和nbytes等同于read和write函數(shù)的三個(gè)參數(shù):描述符、指向讀入或者寫出緩沖區(qū)的指針和讀寫字節(jié)數(shù)。
sendto的to參數(shù)指向一個(gè)含有數(shù)據(jù)報(bào)接收者的協(xié)議地址的套接字地址結(jié)構(gòu),其大小由addrlen參數(shù)指定。recvfrom的from參數(shù)指向一個(gè)將由該函數(shù)在返回時(shí)填寫數(shù)據(jù)報(bào)發(fā)送者的協(xié)議地址的套接字地址結(jié)構(gòu),而在該套接字地址結(jié)構(gòu)中填寫的字節(jié)數(shù)則放在addrlen參數(shù)所指的整數(shù)中返回給調(diào)用者。注意,sendto的最后一個(gè)參數(shù)是一個(gè)整數(shù)值,而recvfrom的最后一個(gè)參數(shù)是一個(gè)指向整數(shù)值的指針。
recvfrom的最后兩個(gè)參數(shù)類似于accept的最后兩個(gè)參數(shù):返回時(shí)其中套接字地址結(jié)構(gòu)的內(nèi)容告訴我們是誰(shuí)發(fā)送了數(shù)據(jù)報(bào)(UDP情況下)或者是誰(shuí)發(fā)起了連接(TCP情況下)。sendto的最后兩個(gè)參數(shù)類似于connect的最后兩個(gè)參數(shù):調(diào)用時(shí)其中套接字地址結(jié)構(gòu)被我們填入數(shù)據(jù)將發(fā)往(UDP情況下)或者與之建立連接(TCP情況下)的協(xié)議地址。
這兩個(gè)函數(shù)都把所讀寫數(shù)據(jù)的長(zhǎng)度作為函數(shù)返回值。在recvfrom使用數(shù)據(jù)報(bào)協(xié)議的典型用途中,返回值就是所接收數(shù)據(jù)報(bào)中的用戶數(shù)據(jù)量。
寫一個(gè)長(zhǎng)度為0的數(shù)據(jù)報(bào)是可行的。UDP情況下,這會(huì)形成一個(gè)只包含一個(gè)IP首部和一個(gè)8字節(jié)UDP首部而沒(méi)有數(shù)據(jù)的IP數(shù)據(jù)報(bào)。這也意味著對(duì)于數(shù)據(jù)報(bào)協(xié)議,recvfrom返回0值是可接受的:他并不像TCP套接字上read返回0值那樣表示對(duì)端已關(guān)閉連接。既然UDP是無(wú)連接的,因此也就沒(méi)有諸如關(guān)閉一個(gè)UDP連接之類的事情。
如果recvfrom的from參數(shù)是一個(gè)空指針,那么相應(yīng)大的長(zhǎng)度參數(shù)(addrlen)也必須是一個(gè)NULL指針,表示我們并不關(guān)心數(shù)據(jù)發(fā)送者的協(xié)議地址。