zoukankan      html  css  js  c++  java
  • WinSock网络编程笔记: 获得本地IP地址

    每次写网络程序都必须编写代码载入和释放winsock库,为了以后方便使用,我们将封装一个CInitSock类来管理Winsock库:

    // initsock.h文件
    
    #include <winsock2.h>
    #pragma comment(lib, "WS2_32")	// 链接到WS2_32.lib
    
    class CInitSock		
    {
    public:
    	CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
    	{
    		// 初始化WS2_32.dll
    		WSADATA wsaData;
    		WORD sockVersion = MAKEWORD(minorVer, majorVer);
    		if(::WSAStartup(sockVersion, &wsaData) != 0)
    		{
    			exit(0);
    		}
    	}
    	~CInitSock()
    	{	
    		::WSACleanup();	
    	}
    };
    

    WSADATA   这个结构被用来存储 被WSAStartup函数调用后返回的 Windows Sockets 数据。它包含Winsock.dll 执行的数据。

    WSAStartup    为了在应用程序当 中调用任何一个Winsock API函数,首先第一件事情就是必须通过WSAStartup函数完成对Winsock服务的初始化,因此需要调用WSAStartup函数。使用 Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明 副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。当一个应用程序调用WSAStartup函数时,操作系统根据请求的Socket版本来搜索相应的 Socket库,然后绑定找到的Socket库到该应用程序中。以后应用程序就可以调用所请求的Socket库中的其它Socket函数了。

    WSACleanup   应用程序或DLL在使用Windows Sockets服务之前必须要进行一次成功的WSAStartup()调 用.当它完成了Windows Sockets的使用后,应用程序或DLL必须调用WSACleanup()将其从Windows Sockets的实现中注销,并且该实现释放为应用程序或DLL分配的任何资源.任何打开的并已建立连接的SOCK_STREAM类型套接口在调用 WSACleanup()时会重置; 而已经由closesocket()关闭却仍有要发送的悬而未决数据的套接口则不会受影响- 该数据仍要发送.   对应于一个任务进行的每一次WSAStartup()调用,必须有一个 WSACleanup()调用.只有最后的WSACleanup()做实际的清除工作;前面的调用仅仅将Windows Sockets DLL中的内置引用计数递减.一个简单的应用程序为确保WSACleanup()调用了足够的次数,可以在一个循环中不断调用WSACleanup()直 至返回WSANOTINITIALISED.


    #include"../common/initsock.h" //添加该头文件
    #include<iostream>
    #include<cstdio>
    
    using namespace std;
    
    CInitSock initsock; //初始化
    
    int main()
    {
    	in_addr addr;
    	char HostName[256];                    //存放主机名
    	int k = ::gethostname(HostName, 256);  //返回本地主机的标准主机名
    	if (k)                                
    	{
    		k = GetLastError();
    	}
    	cout << "当前主机名为: " << HostName << endl;
    
    	hostent *pHost = ::gethostbyname(HostName);//是host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表。之所以主机的地址是一个列表的形式,原因是当一个主机有多个网络接口时,自然有多个地址。
    	for (int i = 0;; i++)
    	{
    		char *p = pHost->h_addr_list[i];
    		if (p == NULL)
    		{
    			break;
    		}
    		memcpy(&addr.S_un.S_addr, p, pHost->h_length);//由p指向地址为起始地址的连续pHost->h_length个字节的数据复制到以addr.S_un.S_addr指向地址为起始地址的空间内。
    		
    		char *IP = ::inet_ntoa(addr);                 //将网络地址转换成“.”点隔的字符串格式
    		cout << "本机IP地址为: " << IP << endl;
    	}
    	
    }

    部分函数介绍:

    gethostname()   
    
    返回本地主机的标准主机名。
    int PASCAL FAR gethostname(char FAR *name, int namelen);   
    name: 一个指向将要存放主机名的缓冲区指针。   
    namelen:缓冲区的长度。
    hostent      是host entry的缩写,该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表。之所以主机的地址是一个列表的形式,原因是当一个主机有多个网络接口时,自然有多个地址。
    
    #define h_addr h_addr_list[0]    h_addr_list中的第一地址。
    
    struct hostent {   
         char *h_name;       //地址的正式名称 
         char **h_aliases;   //空字节-地址的预备名称的指针。
         int h_addrtype;   //地址类型; 通常是AF_INET。
         int h_length;       //地址的比特长度。
         char **h_addr_list;     //零字节-主机网络地址指针。网络字节顺序。
    };
    memcpy
    extern void *memcpy(void *destin, void *source, unsigned n);
    由source指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
    inet_ntoa()    功能是将网络地址转换成“.”点隔的字符串格式。
    
    函数原型: char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
    MSDN上本函数的原型描述为:unsigned long inet_addr( __in const char *cp);
    in:一个表示Internet主机地址的结构。
    
    注释:
    本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。请注意inet_ntoa()返回的字符串存放在WINDOWS套接口实现所分配的内存中。应用程序不应假设该内存是如何分配的。在同一个线程的下一个WINDOWS套接口调用前,数据将保证是有效。
    
    返回值:
    若无错误发生,inet_ntoa()返回一个字符指针。否则的话,返回NULL。其中的数据应在下一个WINDOWS套接口调用前复制出来。
    struct   in_addr的定义如下:
    
    struct   in_addr{
          union {       
                     struct{  
                            unsigned  char   s_b1,s_b2,s_b3, s_b4; 
                      }  S_un_b;   
      
                     struct  {   
                               unsigned  short  s_w1,s_w2;       
                     }  S_un_w;    
    
                      unsigned long  S_addr;  
           } S_un; 
    }; 

     参考博客:https://blog.csdn.net/loverooney/article/details/23298643

  • 相关阅读:
    ios UIWebView截获html并修改便签内容(转载)
    IOS获取系统时间 NSDate
    ios 把毫秒值转换成日期 NSDate
    iOS  如何判断当前网络连接状态  网络是否正常  网络是否可用
    IOS开发 xcode报错之has been modified since the precompiled header was built
    iOS系统下 的手机屏幕尺寸 分辨率 及系统版本 总结
    iOS 切图使用 分辨率 使用 相关总结
    整合最优雅SSM框架:SpringMVC + Spring + MyBatis 基础
    Java面试之PO,VO,TO,QO,BO
    Notes模板说明
  • 原文地址:https://www.cnblogs.com/Romantic-Chopin/p/12451014.html
Copyright © 2011-2022 走看看