zoukankan      html  css  js  c++  java
  • [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 */
    
    
  • 相关阅读:
    摊还分析
    web端手机方向传感器闲谈
    研一一年论文总结(下)
    Jupyter自定义设置详解
    HAProxy实现动静分离和负载均衡
    欧拉项目 323题
    mysql基本操作
    以后的IT路还很长(1)
    【翻译】在Ext JS集成第三方库
    吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring IoC容器BeanFactory和ApplicationContext
  • 原文地址:https://www.cnblogs.com/zhangyangrui/p/13229114.html
Copyright © 2011-2022 走看看