一個(gè)簡單的UDP客戶端/服務(wù)器程序示例,這個(gè)簡單的例子執(zhí)行如下步驟的一個(gè)回射服務(wù)器:
1) 客戶端從標(biāo)準(zhǔn)輸入讀入一行文本,并寫給服務(wù)端
2) 服務(wù)端從網(wǎng)絡(luò)輸入讀入一行文本,并回射給客戶端
3) 客戶端從網(wǎng)絡(luò)輸入讀入這行回射的文件,并顯示在標(biāo)準(zhǔn)輸出上。
下圖描述了這個(gè)簡單的客戶/服務(wù)器:

UDP回射服務(wù)器程序和UDP回射客戶端程序見上篇,略
數(shù)據(jù)報(bào)的丟失
我們的UDP客戶/服務(wù)器例子是不可靠的。如果一個(gè)客戶數(shù)據(jù)報(bào)丟失(譬如說,被客戶主機(jī)與服務(wù)器主機(jī)之間的某個(gè)路由器丟棄),客戶端將永遠(yuǎn)阻塞于dg_cli函數(shù)中的recvfrom調(diào)用,等待一個(gè)永遠(yuǎn)不會(huì)到達(dá)的服務(wù)器應(yīng)答。類似的,如果客戶數(shù)據(jù)報(bào)到達(dá)服務(wù)器,但是服務(wù)器的應(yīng)答丟失了,客戶端也將永遠(yuǎn)阻塞于recvfrom調(diào)用。防止這樣永遠(yuǎn)阻塞的一般方法是給客戶的recvfrom調(diào)用設(shè)置一個(gè)超時(shí)。
僅僅給recvfrom調(diào)用設(shè)置超時(shí)并不是完整的解決辦法。舉例來說,如果確實(shí)超時(shí)了,我們將無從判定超時(shí)的原因是我們的數(shù)據(jù)報(bào)沒有到達(dá)服務(wù)器,還是服務(wù)器的應(yīng)答沒有回到客戶。如果客戶的請(qǐng)求是“從賬戶A往賬戶B轉(zhuǎn)一定數(shù)目的錢”而不是我們的簡單回射服務(wù)器例子,那么請(qǐng)求丟失和應(yīng)帶丟失是極不相同的。因此需要給UDP增加可靠性
驗(yàn)證接收的響應(yīng)
知道客戶臨時(shí)端口號(hào)的任何進(jìn)程都可以給客戶發(fā)送數(shù)據(jù)報(bào),而且這些數(shù)據(jù)報(bào)會(huì)與正常的服務(wù)器應(yīng)答混雜??梢詒ecvform調(diào)用以返回?cái)?shù)據(jù)報(bào)發(fā)送者的IP地址和端口號(hào),保留來自服務(wù)器的應(yīng)答,忽略任何其他的數(shù)據(jù)報(bào)。
如下所示:

如果服務(wù)器是運(yùn)行在一個(gè)只有單個(gè)IP地址的主機(jī)上,那么這個(gè)新版的客戶端能正常工作。然后如果客戶端是多宿的,客戶端就有可能失敗。因?yàn)閞ecvfrom返回的IP地址,可能不是我們發(fā)送指定的IP地址,服務(wù)器可能選擇從其他的IP作為外出接口。
一個(gè)解決辦法是:得到recvfrom返回的IP地址后,客戶端通過在DNS中查找服務(wù)器主機(jī)的名字來驗(yàn)證該主機(jī)的域名而不是IP地址。另一個(gè)解決辦法是:服務(wù)端為每個(gè)IP地址創(chuàng)建一個(gè)套接字,用bind捆綁各自的IP到各自的套接字。這樣,就會(huì)從對(duì)應(yīng)的IP地址上響應(yīng)客戶端。