2010-06-17 64 views
24

我正在寫簡單的服務器/客戶端,並試圖獲取客戶端IP地址並將其保存在服務器端以決定哪個客戶端應該進入關鍵部分。我GOOGLE了幾次,但無法找到合適的方式從襪子結構獲得IP地址。如何從c中的sock結構獲取ip地址?

我相信這是一種從服務器接受來自客戶端的請求後從sock結構中獲取IP的方式。更具體的服務器後的C執行

csock = accept(ssock, (struct sockaddr *)&client_addr, &clen) 

感謝

+0

只是在這裏告訴大家,被檢查的答案在很多方面都是非常糟糕的答案。請爲所有其他程序員的好處,請不要使用它。 – Omnifarious 2017-06-15 06:43:09

回答

36

OK假設你使用的IPV4然後執行以下操作:

struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&client_addr; 
struct in_addr ipAddr = pV4Addr->sin_addr; 

如果你再要的IP地址爲一個字符串,然後做以下:

char str[INET_ADDRSTRLEN]; 
inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); 

IPV6是很容易的,以及...

struct sockaddr_in6* pV6Addr = (struct sockaddr_in6*)&client_addr; 
struct in6_addr ipAddr  = pV6Addr->sin6_addr; 

並獲得一個字符串幾乎是相同的IPV4

char str[INET6_ADDRSTRLEN]; 
inet_ntop(AF_INET6, &ipAddr, str, INET6_ADDRSTRLEN); 
+2

你忘了將'str'緩衝區傳遞給'inet_ntop()'。而'sin_addr'是一個結構 - 必須使用'sin_addr.s_addr'。值得注意的是,IPv4地址以網絡字節順序存儲,並將其視爲十六進制數,因此需要使用'ntohl(pV4Addr-> sin_addr.s_addr)'。 – Dummy00001 2010-06-17 12:22:15

+0

得分......你也錯過了我不使用小寫字母「in6_addr」;)在ntohl前面,我並不經常打擾,因爲我仍然可以進行平等檢查(提供的都是網絡順序),它會打破inet_ntop (不是嗎?)。 – Goz 2010-06-17 12:58:42

+2

這個問題被標記爲C - 你不能在'struct sockaddr_in *'之類的類型中遺漏'struct'。此外,IPV4方法應該使用'struct in_addr'而不是'int'來存儲地址,類似於你所展示的IPV6方法。 – caf 2010-06-18 05:57:43

21

假設client_addrstruct sockaddr_in(這通常是這樣)。您可以從client_addr.sin_addr.s_addr獲取IP地址(作爲32位無符號整數)。

可以這種方式轉換爲字符串:

printf("%d.%d.%d.%d\n", 
    int(client.sin_addr.s_addr&0xFF), 
    int((client.sin_addr.s_addr&0xFF00)>>8), 
    int((client.sin_addr.s_addr&0xFF0000)>>16), 
    int((client.sin_addr.s_addr&0xFF000000)>>24)); 
+27

您應該使用inet_ntoa()而不是手動操縱位。 – 2010-06-18 01:15:33

+12

'inet_ntoa'不是線程安全的,儘管對於使用它的大多數情況來說可能並不重要。一個安全的選擇是'inet_ntop'。 – jweyrich 2013-04-29 05:13:38

+3

這不適用於任何大端架構。 – Ternvein 2015-02-11 05:50:53

26

提取IP地址和端口號,更容易和正確的方法是:

printf("IP address is: %s\n", inet_ntoa(client_addr.sin_addr)); 
printf("port is: %d\n", (int) ntohs(client_addr.sin_port)); 

肥皂盒的接受的答案不會對所有體系結構都是正確的。請參閱Big and Little Endian