Linux 平台上更加准确获取到默认网关的类似实现方法,但这可能需要足够的系统权限。
Linux 从多个IPv4路由表内存文件之中获取默认网关IP地址_liulilittle的博客-CSDN博客
本方法路子野,其原理是假定用户不会配置 8.8.8.8 的IP路由,其始终保持走默认网关出去,所以我们只需要建一个 Tcpip-socket 实例,并且不绑定任何网卡,直接异步方式向外 connect,同步会导致长时间阻塞,我们仅仅只是为了获取 connet 时默认分配出去的网卡IP地址。
其下为实现方法:
UInt32 Network::TestInterfaceAddress() {
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) {
return IPEndPoint::NoneAddress;
}
if (!Socket::SetNonblocking(fd, true)) {
Socket::Closesocket(fd);
return IPEndPoint::NoneAddress;
}
struct sockaddr_in connect_addr;
memset(&connect_addr, 0, sizeof(connect_addr));
connect_addr.sin_addr.s_addr = inet_addr("8.8.8.8");
connect_addr.sin_port = 53;
connect_addr.sin_family = AF_INET;
int hr = connect(fd, (struct sockaddr*)&connect_addr, sizeof(connect_addr));
if (hr == -1) {
hr = errno;
if (hr != EINPROGRESS) {
Socket::Closesocket(fd);
return IPEndPoint::NoneAddress;
}
}
struct sockaddr_in sock_addr;
int sock_len = sizeof(sock_addr);
memset(&sock_addr, 0, sizeof(sock_addr));
if (getsockname(fd, (struct sockaddr*)&sock_addr, (socklen_t*)&sock_len)) {
Socket::Closesocket(fd);
return IPEndPoint::NoneAddress;
}
else {
Socket::Closesocket(fd);
}
if (sock_addr.sin_family != AF_INET) {
return IPEndPoint::NoneAddress;
}
return sock_addr.sin_addr.s_addr;
}