Windows/Linux跨平台支持C++获取主机ip地址列表(支持IPv4和IPv6)

xingyun86 2020-10-21 996

Windows/Linux跨平台支持C++获取主机ip地址列表(支持IPv4和IPv6)

// EnumHostAddr.h : Include file for standard system include files,
// or project specific include files.
#pragma once
#include <iostream>
// TODO: Reference additional headers your program requires here.
#include <string>
#include <thread>
#ifdef _MSC_VER
#define  _WINSOCK_DEPRECATED_NO_WARNINGS 
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ifaddrs.h>
#endif
#pragma pack(1)
typedef struct __xxx__ { uint8_t v; };
#pragma pack()
#include <vector>
class SockUtil {
public:
#ifdef _MSC_VER
	WSADATA wsadata = { 0 };
#endif
	SockUtil()
	{
#ifdef _MSC_VER
		//初始化套接字库
		WORD w_req = MAKEWORD(2, 2);//版本号
		int err;
		err = WSAStartup(w_req, &wsadata);
		if (err != 0)
		{
			std::cout << "Initialize winsock library failed!" << std::endl;
		}
		else
		{
			std::cout << "Initialize winsock library ok!" << std::endl;
		}
		//检测版本号
		if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
		{
			std::cout << "Winsock library version failed!" << std::endl;
			WSACleanup();
		}
		else
		{
			std::cout << "Winsock library version ok!" << std::endl;
		}
#endif
	}
	~SockUtil()
	{
#ifdef _MSC_VER
		WSACleanup();
#endif
	}
private:
	int enum_host_addr(std::vector<std::string> & sv, int af/*= AF_INET or AF_INET6*/)
	{
		int ret = 0;
		char ip[65] = { 0 };
		struct sockaddr_in* addr = nullptr;
#ifdef _MSC_VER
		char host_name[33] = { 0 };
		struct addrinfo hints = { 0 };
		struct addrinfo* res = nullptr;
		struct addrinfo* cur = nullptr;
		memset(&hints, 0, sizeof(struct addrinfo));
		hints.ai_family = af; /* Allow IPv4 */
		hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
		hints.ai_protocol = 0; /* Any protocol */
		hints.ai_socktype = SOCK_STREAM;
		ret = gethostname(host_name, sizeof(host_name) / sizeof(*host_name));
		if (ret == 0)
		{
			ret = getaddrinfo(host_name, nullptr, &hints, &res);
			if (ret == 0) {
				for (cur = res; cur != nullptr; cur = cur->ai_next) {
					addr = (struct sockaddr_in*)cur->ai_addr;
					std::cout << inet_ntop(af, &addr->sin_addr, ip, sizeof(ip) / sizeof(*ip)) << std::endl;
					sv.push_back(ip);
				}
				freeaddrinfo(res);
			}
		}
#else
		struct ifaddrs* ifa = nullptr;
		struct ifaddrs* oifa = nullptr;
		ret = getifaddrs(&ifa);
		if (ret == 0)
		{
			oifa = ifa;
			while (ifa != nullptr)
			{
				// IPv4 排除localhost
				if (ifa->ifa_addr != nullptr
					&& ifa->ifa_addr->sa_family == af
					&& strncmp(ifa->ifa_name, "lo", 2) != 0)
				{
					addr = (struct sockaddr_in*)ifa->ifa_addr;
					std::cout << inet_ntop(af, &addr->sin_addr, ip, sizeof(ip) / sizeof(*ip)) << std::endl;
					sv.push_back(ip);
				}
				ifa = ifa->ifa_next;
			}
			freeifaddrs(oifa);
		}
#endif
		return ret;
	}
public:
	int enum_host_addr_ipv4(std::vector<std::string>& sv)
	{
		return enum_host_addr(sv, AF_INET);
	}
	int enum_host_addr_ipv6(std::vector<std::string>& sv)
	{
		return enum_host_addr(sv, AF_INET6);
	}
public:
	static SockUtil* Inst()
	{
		static SockUtil SockUtilInstance;
		return &SockUtilInstance;
	}
};

用法:

// EnumHostAddr.cpp : Defines the entry point for the application.
//
#include "EnumHostAddr.h"
int main(int argc, char** argv) {
	std::vector<std::string> svIpv4;
	SockUtil::Inst()->enum_host_addr_ipv4(svIpv4);
	return 0;
}


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回