获取本机计算机名与IP地址(1.讲解2.代码)
1.讲解
第1步:初始化套接字,现已封装在头文件中,只需包含进头文件,然后用那对象名,定义一个类变量即可运行
第2步:获取主机名gethostname即可
第3步:获取主机IP---gethostbyname(主机名),不过有点问题,因为格式不匹配,我需要的是CString或char*格式,而它返回的是hostent格式,怎么办?
---解决办法:1.inet_ntoa(addr),可以返回char*
2.但是addr怎么来?是in_addr addr;这个函数中有一个专门接受IP地址的,通过指针转移即可(memcpy),详见代码
-----------一共分2个文件,1个.CPP 1个.H--------
--------------.CPP源文件--------------------
#include"Initsock.h"//将初始化套接字封装在头文件中了,一定要初始化,否则不能获得主机名与IP地址
CInitsock initsock; //让其头文件运行,初始化套接字
#include<iostream>
using namespace std;
void main()
{
// 取得本地主机名称
char szHost[256];gethostname(szHost, 256);cout<<"主机名:"<<szHost<<endl;
// 通过主机名得到地址信息
hostent *pHost = gethostbyname(szHost);
// 打印出所有IP地址
in_addr addr;
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);
char *szIp =inet_ntoa(addr);
cout<<"本机IP地址:"<<szIp<<endl;
}
getchar();
}
---------------.H头文件-------------------
#include<WINSOCK2.H>
#pragma comment(lib, "WS2_32") // 链接到WS2_32.lib
class CInitsock
{
public:
CInitsock()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
return;
}
/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
WSACleanup( );
return;
}
}
~CInitsock()
{
WSACleanup();
}
};
---------------
2.2.3 -3使用GetAdaptersInfo获取网卡详细信息
#include <windows.h>
#include <Iphlpapi.h>
#include <stdio.h>
#pragma comment(lib,"Iphlpapi.lib")
int main()
{
PIP_ADAPTER_INFO pAdapterInfo;ULONG ulOutbufLen = sizeof(IP_ADAPTER_INFO);//注意是ULONG类型,而非PULONG类型
pAdapterInfo = ( IP_ADAPTER_INFO *)malloc( sizeof(IP_ADAPTER_INFO) );//为其动态分配内存,若大小不够,后面会有调整
if ( ERROR_BUFFER_OVERFLOW == GetAdaptersInfo( pAdapterInfo, &ulOutbufLen) )
{//MSDN上介绍,因为获取的消息,可能超过预先设置的缓冲区长度,造成返回,而一旦返回获取的资料将为空,此处为防止这种情况发生,
free(pAdapterInfo);//可以测试一下结果,去掉这部分代码后,返回值为空.此处重构,直到成功
pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutbufLen); //第1次大小不够,第2次返回所需长度
}
if ( ERROR_SUCCESS == GetAdaptersInfo( pAdapterInfo, &ulOutbufLen ))//MSDN上是那样写,也可写成NO_ERROR,都正确
{
// pAdapter = pAdapterInfo;//PIP_ADAPTER_INFO pAdapter = NULL;//原始代码有写,其实写不写结果一样.
while ( pAdapterInfo ) //当传递的值为NULL后,循环结束
{
printf("Adapter Name: /t%s/n", pAdapterInfo->AdapterName);
printf("Adapter Desc: /t%s/n", pAdapterInfo->Description);
printf("MAC Addr: /t%02x-%02x-%02x-%02x-%02x-%02x/n",
pAdapterInfo->Address[0], //注意此处是数组格式,网上有的没有[0][1]等,
pAdapterInfo->Address[1],
pAdapterInfo->Address[2],
pAdapterInfo->Address[3],
pAdapterInfo->Address[4],
pAdapterInfo->Address[5]//,pAdapterInfo->Address[6],如果你想知道第7个是个什么值?可以一试,但是值为00(即空值)
);
printf("IP Address: /t%s/n", pAdapterInfo->IpAddressList.IpAddress.String);
printf("IP Mask: /t%s/n", pAdapterInfo->IpAddressList.IpMask.String);
printf("Gateway: /t%s/n", pAdapterInfo->GatewayList.IpAddress.String);
pAdapterInfo = pAdapterInfo->Next;
}
}//getchar();//起暂停作用
return 0;
}
备注:GetAdaptersInfo函数的获得网卡的信息还有很多,有兴趣的可以查看MSDN深入了解,注意一定是高版本的MSDN,否则低版本的有些东西没有
下面的一幅图,是更专门介绍IP_ADAPTER_INFO信息,为你扫除疑惑
--------
时间协议的代码:------分源文件与头文件------
---------------源文件-----------------
//
// NetTime.cpp文件
#include "InitSock.h"
CInitSock initSock;
#include <stdio.h>
void SetTimeFromTP(ULONG ulTime) // 根据时间协议返回的时间设置系统时间
{
// Windows文件时间是一个64位的值,它是从1601年1月1日中午12:00到现在的时间间隔,
// 单位是1/1000 0000秒,即1000万分之1秒(100-nanosecond )
FILETIME ft;
SYSTEMTIME st;
// 首先将基准时间(1900年1月1日0点0分0秒0毫秒)转化为Windows文件时间
st.wYear = 1900;
st.wMonth = 1;
st.wDay = 1;
st.wHour = 0;
st.wMinute = 0;
st.wSecond = 0;
st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ft);
// 然后将Time Protocol使用的基准时间加上以及逝去的时间,即ulTime
LONGLONG *pLLong = (LONGLONG *)&ft;
// 注意,文件时间单位是1/1000 0000秒,即1000万分之1秒(100-nanosecond )
*pLLong += (LONGLONG)10000000 * ulTime;
// 再将时间转化回来,更新系统时间
FileTimeToSystemTime(&ft, &st);
SetSystemTime(&st);
}
int main()
{
SOCKET s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//TCP协议
if(s == INVALID_SOCKET)
{
printf(" Failed socket() /n");
return 0;
}
// 填写远程地址信息,连接到时间服务器
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(37);
// 这里使用的时间服务器是129.132.2.21,更多地址请参考http://tf.nist.gov/service/its.htm
servAddr.sin_addr.S_un.S_addr = inet_addr("64.236.96.53 ");//注:这个IP,是不断更新的,最好网上能用的
if(::connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
{
printf(" Failed connect() /n");
return 0;
}
// 等待接收时间协议返回的时间。学习了Winsock I/O模型之后,最好使用异步I/O,以便设置超时
ULONG ulTime = 0;
int nRecv = ::recv(s, (char*)&ulTime, sizeof(ulTime), 0);
if(nRecv > 0)
{
ulTime = ntohl(ulTime);
SetTimeFromTP(ulTime);
printf(" 成功与时间服务器的时间同步!/n");
}
else
{
printf(" 时间服务器不能确定当前时间!/n");
}
::closesocket(s);
return 0;
}
--------------头文件------------------
//
// 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();
}
};
使用效果:恢复你电脑时间为标准时间,例:现在6月22日22:30分,你现在把它改成5月17日19点45分,运行此程序后,会自动恢复你的时间为标准时间即,6月22日22:30分