[C++]输出本机所有ip地址

int main()
{
	char name[256];
	gethostname(name, sizeof(name));

	in_addr addr;
	addrinfo* res;
	addrinfo hints;
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;     /* Allow IPv4 */
	hints.ai_flags = AI_PASSIVE;/* For wildcard IP address */
	hints.ai_protocol = 0;         /* Any protocol */
	hints.ai_socktype = SOCK_STREAM;
	getaddrinfo(name,NULL,&hints,&res);

	while (res != NULL) {
		struct sockaddr* temp = res->ai_addr;
		int c;
		for (int i = 0; i < 3; ++i) {
			c = (int)(unsigned char)(*temp).sa_data[i + 2];
			cout << c << '.';
		}
		c = (int)(unsigned char)(*temp).sa_data[5];
		cout << c << endl;
		res = res->ai_next;
	}
}

 gethostname 函数获得了我的电脑的名字 "DESKTOP-GA8048R"

将这个名字与hint输入到getaddrinfo 中去,输出地址信息链表到res指针中

接下来遍历res指针的链表,将地址输出,得到:

192.168.222.1
192.168.146.1
192.168.3.71

注意,192.168.222.1这4位分别储存在char[14]数组sa_data的4个char中,需要先转换为无符号char,再转换为数字int。

上面3个ip地址有一个是真正的网卡地址,另外两个是虚拟机vmware的地址。

上面我们用到的是sockaddr,它的定义如下

typedef struct sockaddr {
#if (_WIN32_WINNT < 0x0600)
    u_short sa_family;
#else
    ADDRESS_FAMILY sa_family;           // Address family.
#endif //(_WIN32_WINNT < 0x0600)

    CHAR sa_data[14];                   // Up to 14 bytes of direct address.
} SOCKADDR, *PSOCKADDR, FAR *LPSOCKADDR;

  

下面尝试结构sockaddr_in,它的定义如下

typedef struct sockaddr_in {
#if(_WIN32_WINNT < 0x0600)
    short   sin_family;
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;
#endif //(_WIN32_WINNT < 0x0600)
    USHORT sin_port;
    IN_ADDR sin_addr;   //储存地址的地方
    CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;

储存地址有3种方式:4个byte,2个word,和一个ulong。

typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

观察他们的值:

注意到43200=168*256+192

  478=1*256+222

这说明本机使用的是little endian,高位放在后面。

同理31369408=1<<24+222<<16+168<<8+192

代码基本相同,只不过要加上强制类型转换。

int main()
{
    char name[256];
    gethostname(name, sizeof(name));

    in_addr addr;
    addrinfo* res;
    addrinfo hints;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_INET;     /* Allow IPv4 */
    hints.ai_flags = AI_PASSIVE;/* For wildcard IP address */
    hints.ai_protocol = 0;         /* Any protocol */
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo(name,NULL,&hints,&res);

    while (res != NULL) {
        struct sockaddr_in* temp = (sockaddr_in*)res->ai_addr;
        int c;
        
        c = (int)(*temp).sin_addr.S_un.S_un_b.s_b1;
        cout << c << '.';
        c = (int)(*temp).sin_addr.S_un.S_un_b.s_b2;
        cout << c << '.';
        c = (int)(*temp).sin_addr.S_un.S_un_b.s_b3;
        cout << c << '.';
        c = (int)(*temp).sin_addr.S_un.S_un_b.s_b4;
        cout << c <<endl;

        res = res->ai_next;
    }
}

hints指示了我们想要收到什么样的地址。假如删掉hints,输入参数由&hints转变为NULL,那么输出为:

0.0.0.0
0.0.0.0
0.0.0.0
192.168.222.1
192.168.146.1
192.168.3.71

在局部变量窗口中发现,前3个0.0.0.0对应的 sin_family为23,也就是ipv6,而后面三个地址对应的 sin_family为2,也就是ipv4

由于之前hint限定了ipv4,所以删掉后出现了ipv6的地址。但至于为什么是0.0.0.0,我也不知道,因为我没有开过ipv6。

hints.ai_family = AF_INET;     /* Allow IPv4 */

原文地址:https://www.cnblogs.com/zhangyangrui/p/13229114.html