簡體   English   中英

理解 INADDR_ANY 進行套接字編程

[英]Understanding INADDR_ANY for socket programming

我正在嘗試編寫一些套接字,因此在服務器端,我使用htonl(INADDR_ANY) 在我理解的范圍內,在我看來,這個函數會生成一個隨機 IP(我說得對嗎?)。 事實上,我想將我的套接字與我的localhost綁定。 但是如果我運行這個

printf("%d",htonl(INADDR_ANY));

我得到 0 作為返回值。 有人可以帶來一些解釋嗎?

  1. INADDR_ANY bind()不會“生成隨機 IP”。 它將套接字綁定到所有可用的接口

  2. 對於服務器,您通常希望綁定到所有接口——而不僅僅是“本地主機”。

  3. 如果您只想將套接字綁定到本地主機,則語法為my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1"); ,然后調用bind(my_socket, (SOCKADDR *) &my_sockaddr, ...)

  4. 碰巧, INADDR_ANY是一個常數,恰好等於“零”:

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

     # define INADDR_ANY ((unsigned long int) 0x00000000) ... # define INADDR_NONE 0xffffffff ... # define INPORT_ANY 0 ...
  5. 如果您還不熟悉它,我強烈建議您查看 Beej 的套接字編程指南:

    http://beej.us/guide/bgnet/

由於人們仍在閱讀本文,因此請補充說明:

男人 (7) ip :

當一個進程想要接收新的傳入數據包或連接時,它應該使用bind(2)將套接字綁定到本地接口地址。

在這種情況下,只有一個 IP 套接字可以綁定到任何給定的本地(地址、端口)對。 當在綁定調用中指定 INADDR_ANY 時,套接字將綁定到所有本地接口。

當在未綁定的套接字上調用listen(2) 時,該套接字將自動綁定到本地地址設置為 INADDR_ANY 的隨機空閑端口。

當在未綁定的套接字上調用connect(2) 時,該套接字將自動綁定到隨機空閑端口或本地地址設置為 INADDR_ANY 的可用共享端口...

有幾個特殊地址: INADDR_LOOPBACK (127.0.0.1) 總是通過環回設備引用本地主機; INADDR_ANY (0.0.0.0) 表示用於綁定的任何地址...

還:

bind() — 將名稱綁定到套接字

如果 (sin_addr.s_addr) 字段設置為常量 INADDR_ANY,如 netinet/in.h 中所定義,則調用者請求將套接字綁定到主機上的所有網絡接口。 隨后,來自所有接口(與綁定名稱匹配)的 UDP 數據包和 TCP 連接被路由到應用程序。 當服務器向多個網絡提供服務時,這變得很重要。 通過不指定地址,服務器可以接受為其端口發出的所有 UDP 數據包和 TCP 連接請求,而不管請求到達的網絡接口。

當您不需要將套接字綁定到特定 IP 時使用INADDR_ANY 當您在調用bind()時將此值用作地址時,套接字將接受與機器所有 IP 的連接。

要將套接字與localhost綁定,在調用綁定函數之前,應正確設置 sockaddr_in 結構的 sin_addr.s_addr 字段。 可以通過以下方式獲得適當的值

my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")

或由

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);

INADDR_ANY指示偵聽套接字綁定到所有可用接口。 這與嘗試綁定到inet_addr("0.0.0.0") 為了完整起見,我還將提到 IPv6 也有IN6ADDR_ANY_INIT ,這與嘗試綁定到 IPv6 套接字的::地址相同。

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

另請注意,當您將 IPv6 套接字綁定到IN6ADDR_ANY_INIT您的套接字將綁定到所有 IPv6 接口,並且也應該能夠接受來自 IPv4 客戶端的連接(盡管 IPv6 映射地址)。

INADDR_ANY 是一個常量,在 value 中包含 0。 僅當您想從不關心 ip-add 的所有活動端口進行連接時才使用。 所以如果你想連接任何特定的 ip 你應該提到像 my_sockaddress.sin_addr.s_addr = inet_addr("192.168.78.2")

當你有一個服務器時,你創建一個套接字,然后將它綁定到一個 IP 和端口,這為套接字提供了一種基於唯一的套接字類型、地址族、IP 和端口進行識別的唯一方式。 然后使用listen() 將套接字設置為服務器模式,然后執行accept(),它等待一個連接,該連接將具有目標參數的入站數據包,這些數據包會在該套接字上排隊。

當你有一個客戶端時,你創建一個套接字,然后將套接字連接()到遠程 IP 和端口,如果它還沒有被綁定,它也會將 0.0.0.0 和一個隨機未使用的臨時端口綁定到套接字使用 bind(INADDR_ANY, 0) 到 IP 和端口。 connect() 連接時返回,並使用 IP 和端口作為出站數據包中的源地址,其中 0.0.0.0 始終由操作系統替換為當前內部 IP,然后您使用 sendall 發送應用程序數據。

INADDR_ANY 比以編程方式獲取計算機當前的內部 IP 更快,該 IP 可能隨時更改,並且端口上將不再接收數據包,但它們仍會在 0.0.0.0 上接收,因為它是任何地址。

請注意,套接字可以綁定到 0.0.0.0,但不能綁定到端口 0,因為它是一個通配符,可以為套接字提供一個隨機的臨時端口,因此當您使用 bind(INADDR_ANY, 0) 時,它綁定到 0.0.0.0 和一個隨機臨時端口。

#include <arpa/inet.h>                                                                     
.                                                                                   
.                                                                                        
tcpsock.sin_addr.s_addr = inet_addr("192.168.1.2")

為我工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM