2010-06-17 60 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