zoukankan      html  css  js  c++  java
  • 网络编程实验1_(9)获取本机的IP地址(C++代码)

    #define  _WINSOCK_DEPRECATED_NO_WARNINGS
    #include<iostream>
    #include<WinSock2.h>
    #include<string>
    #pragma comment(lib,"ws2_32.lib")
    
    using namespace std;
    
    int main()
    {
        WSADATA wsaData;         // WSADATA结构包含有关Windows套接字实现的信息。
        WORD wVersionRequest;     // wVersionRequested 为 WinSock 规范的版本号,低字节为主版本号,高字节为副版本号(修正版本号)
        int iResult;             // WSAStartup()的返回值,如果为零,则成功启动网络库
        char name[256];          // 指向接收本地主机名的缓冲区的指针。
        PHOSTENT hostinfo;         // PHOSTENT类型,本质上是一个指向hostent的结构体指针
    
    
        wVersionRequest = MAKEWORD(2, 2);
        iResult = WSAStartup(wVersionRequest, &wsaData);
        if (0 != iResult) {
            switch (iResult)
            {
                case WSASYSNOTREADY:
                    cout << "底层网络子系统还没有准备好进行网络通信。" << endl;
                    break;
                case WSAVERNOTSUPPORTED:
                    cout << "此特定的Windows Sockets实现不提供所请求的Windows Sockets支持的版本。" << endl;
                    break;
                case WSAEINPROGRESS:
                    cout << "正在执行阻塞Windows Sockets 1.1操作。" << endl;
                    break;
                case WSAEPROCLIM:
                    cout << "已达到Windows Sockets实现支持的任务数量的限制。" << endl;
                    break;
                case WSAEFAULT:
                    cout << "lpWSAData参数不是有效指针。" << endl;
                    break;
            
            }
        }
    
        /*
            确认WinSock DLL支持2.2。注意,如果DLL支持的版本除2.2外大于2.2,它仍将在wversion中返回2.2,因为这是我们请求的版本
        */
    
        if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion != 2)) {
            cout << "找不到Winsock.dll的可用版本" << endl;
            WSACleanup();
            return 1;
        }
        else
            cout << "发现了Winsock 2.2 DLL" << endl;
    
    
        /*
            gethostname中有两个参数,第一个name是指向接收主机名的缓冲区的指针,第二个参数是缓冲区的长度(以字节为单位)
            gethostbyname中的参数是域名字符串或者指向主机名的指针
            LPCSTR是Win32和VC++所使用的一种字符串数据类型。LPCSTR被定义成是一个指向以''结尾的常量字符的指针。
            inet_ntoa函数将(IPv4)Internet网络地址转换为Internet标准虚数点分十进制格式的ASCII字符串。
            in_addr结构表示IPv4 Internet地址。
            hostinfo在开头定义了,它是PHOSTENT类型,本质上是一个指向hostent的结构体指针,所以虽然没把hostent在代码中写出来,但必须弄清楚
            h_addr_list,这个是地址列表,是hostent结构体中最重要的成员变量,通过该成员以整数形式保存域名对应的 IP 地址
            
        */
        string ServAddr;
        if (gethostname(name, sizeof(name)) == 0) {
            if ((hostinfo = gethostbyname(name)) != NULL) {
                //LPCSTR ip = inet_ntoa(*(struct in_addr*) * hostinfo->h_addr_list);
                ServAddr = inet_ntoa(*(struct in_addr*) * hostinfo->h_addr_list);
                //ServAddr = ip;
                cout << "本机(此处作为服务器)的IP 为:" << ServAddr << endl;
                //cout << "本机(此处作为服务器)的IP 为:" << ip << endl;
           //如果将被注释掉的这三行来代替这两行代码的话也是可以的
    } } else { switch (gethostname(name, sizeof(name))) { case WSAEFAULT: cout << "name参数是空指针,或者不是用户地址空间的有效部分。如果namelen参数指定的缓冲区大小太小,无法容纳完整的主机名,也会返回此错误。" << endl; break; case WSANOTINITIALISED: cout << "在使用此函数之前,必须进行成功的WSAstartup调用。" << endl; break; case WSAENETDOWN: cout << "网络子系统失败。" << endl; break; case WSAEINPROGRESS: cout << "阻塞Windows套接字1.1调用正在进行,或者服务提供者仍在处理回调函数。" << endl; break; } } WSACleanup(); // 在socket编程中,必须以WSACleanup()结尾 system("pause"); return 0; }

    和上一篇网络编程实验1_(8)获得给定域名的IP地址(C++代码)一样,我通常喜欢把详细的解释放在注释中。

    但是获得本机的IP地址和获得给定域名的IP地址有何区别呢?

    相同之处在于我们使用的获得IP地址的方法都是通过gethostbyname()这个函数实现的。

    这个函数的返回值为一个结构体指针,指向的结构体是hostent,可以通过转到定义查看,

     

    我在程序中使用的就是这个结构体中的成员变量h_addr_list,这其实是一个指针数组,

    用来存放解析出来的多个IP地址。

    和获得给定域名IP地址不同的是,获得本机的IP地址用到了gethostname()这个函数。

    这个函数有两个参数,第一个参数是指向接收主机名的缓冲区的指针,别被修饰词绕晕了,它是指向缓冲区的指针。

    第二个参数是这个缓冲区的大小。

    至于这个缓冲区的大小该设置为多少,MSDN上给出的解释是这样的(我翻译过后的):

     所以我也就索性设置为了256字节。

    这个函数如果运行成功了,返回一个零,否则返回一个错误码。

    至于错误码的含义,你可以不用搞清楚,至少对于有耐心看我这个菜鸟写的博客的你来说,应该是没有任何意义的。

    所以如果你想简单一点,可以把这个啰嗦的switch case去掉,从else开始,直接删掉也是没有任何问题的。

    这个任务最重要的是理解hostent这个结构体,以及如何将这个结构体的成员变量中得到IP地址,并转换为我们需要的形式。

    如果你觉得我讲的不够清楚的,可以看看我之前的博客,或者去网上查一查hostent、以及inet_ntoa()等等。

  • 相关阅读:
    .net core ef动态orderby
    .Net Core 2.*+ InfluxDB+Grafana+App Metrics实时性能监控
    .net core 第三方工具包集合
    .net core appsetting/获取配置文件
    appium处理混合APP_获取上下文(切换句柄)
    Linux平时常用命令_查看进程_监控日志等命令
    手机monkey测试BUG重现及解决方法
    postman常用公共函数
    Jmeter远程运行_多机联合负载
    httpclient向浏览器发送get和post请求
  • 原文地址:https://www.cnblogs.com/cyx-b/p/12410314.html
Copyright © 2011-2022 走看看