2011-08-01 80 views
2

我見過兩個例子,說明客戶端套接字如何接收來自服務器的消息。爲了從服務器接收UDP消息,應該綁定客戶端套接字?

實施例1:

服務器代碼 http://man7.org/tlpi/code/online/book/sockets/ud_ucase_sv.c.html

客戶機代碼 http://man7.org/tlpi/code/online/book/sockets/ud_ucase_cl.c.html

客戶程序創建一個套接字和插座結合的地址,從而使服務器可以發送其答覆。

if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1) 
    errExit("bind"); // snippet from ud_ucase_cl.c 

實施例2:

服務器代碼 http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_sv.c.html

客戶機代碼 http://man7.org/tlpi/code/online/book/sockets/i6d_ucase_cl.c.html

在例2中,客戶機代碼不結合其與地址插座。

問題

是有必要的客戶端代碼,以便從服務器接收消息的地址綁定套接字?

爲什麼在第一個例子中,我們必須將客戶端套接字與地址綁定,爲什麼我們不必在第二個示例中?

回答

1

的差異是socket family - 第一個例子使用AF_UNIX,而第二不AF_INET6。據Stevens UNP你需要明確bind路徑爲Unix客戶端插口使服務器有一個路徑名,它可以發送其答覆:

...發送數據報的未綁定的Unix域數據報套接字不會隱式綁定套接字的路徑名。因此,如果我們忽略這一步,服務器對 recvfrom電話...返回一個空的路徑...

這是不需要INET{4,6}插座,因爲他們是「自動綁定」到一個臨時端口。

1

對於客戶端(TCP)或發送方(UDP),調用bind()是可選的;它是一種指定界面的方法。假設你有兩個接口,這兩者都是可路由到您的目的地:

eth0: 10.1.1.100/24 
eth1: 10.2.2.100/24 

route: 10.1.1.0/24 via 10.2.2.254 # router for eth1 
     0.0.0.0  via 10.1.1.254 # general router 

現在,如果你只說對connect()12.34.56.78,你不知道哪個本地接口的配料連接的本地端。首先通過調用bind()來做出具體的描述。

UDP流量也是如此:如果沒有bind() ing,您的sendto()將使用隨機的源地址和端口,但使用bind()可以使源特定。

+0

那麼爲什麼在第二個例子中,我們不必使用綁定,仍然能夠發送消息到服務器? – q0987

+0

你可以*總是*發送消息。您只是無法控制源接口和​​端口。 –

1

如果您在連接/發送內容之前沒有綁定AF_INET/AF_INET6客戶端套接字,TCP/IP堆棧將自動將其綁定到出站地址上的臨時端口。

與此不同,UNIX域套接字(AF_UNIX)在發送時不會自動綁定,因此您可以通過SOCK_DGRAM發送消息,但無法獲得任何答覆。

相關問題