场景
- 开发
Win32
本地程序时,有时候需要本地启动一个Socket
服务,监听客户端的访问。而其他机器的客户端访问肯定是需要知道这个机器的IP
地址才能连接,那么如何获取服务器本机的IPv4
地址呢?
说明
-
获取本机的
IP
地址,可以通过<winsock.h>
的gethostbyname
函数获得。这个函数在MSDN
上不建议使用,推荐使用的是<winsock2.h>
的getaddrinfo
函数,新版的getaddrinfo
函数可以获取IPv6
地址。但是兼容低版本的系统gethostbyname
还是可以用的,至少目前在Win11
上还可以使用。 -
无论是使用
<winsock.h>
还是<winsock2.h>
,都需要在全局环境(main)
里调用一次WSAStartup
初始化winsock(2)
库,并且在不需要使用winsock(2)
时调用WSACleanup();
释放库资源。
例子
-
以下是获取本机所有
IPv4
的例子。 -
需要链接
Ws2_32.lib
库.
#include <Windows.h>
#include <winsock.h>
#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;
static shared_ptr<vector<string>> QueryAllLocalIpv4()
{
auto hostname = gethostbyname(NULL);
if (!hostname) {
cout << "Error Code: " << WSAGetLastError() << endl;
return nullptr;
}
char **pAlias = NULL;
int i = 0;
cout << "Official name: " << hostname->h_name << endl;
for (pAlias = hostname->h_aliases; *pAlias != 0; pAlias++)
cout << "Alternate name #" << ++i << ":" << *pAlias << endl;
if (hostname->h_addrtype != AF_INET)
return nullptr;
struct in_addr addr;
auto result = make_shared<vector<string>>();
while (hostname->h_addr_list[i] != 0) {
addr.s_addr = *(u_long *)hostname->h_addr_list[i++];
auto address = inet_ntoa(addr);
cout << "IPv4 Address #" << i << ":" << address << endl;
result->push_back(address);
}
return result;
}
int main()
{
// Initialize Winsock
WSADATA wsaData;
auto iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
auto result = QueryAllLocalIpv4();
for (size_t i = 0; result && (i < result->size()); ++i)
cout << result->at(i) << endl;
WSACleanup();
return 0;
}
输出
Official name: QI7
IPv4 Address #1:192.168.3.38
192.168.3.38