networkinterface.cpp.svn-base

来自「很好用的网络封装库,不熟悉网络编程的人也可以使用。使用风格良好的标准c++编写。」· SVN-BASE 代码 · 共 682 行 · 第 1/2 页

SVN-BASE
682
字号

namespace Poco {
namespace Net {

	
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
	FastMutex::ScopedLock lock(_mutex);
	NetworkInterfaceList result;
	DWORD rc;

#if defined(POCO_HAVE_IPv6)
	// On Windows XP/Server 2003 and later we use GetAdaptersAddresses.
	PIP_ADAPTER_ADDRESSES pAdapterAddresses;
	PIP_ADAPTER_ADDRESSES pAddress = 0;
	ULONG addrLen     = sizeof(IP_ADAPTER_ADDRESSES);
	pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[addrLen]);
	// Make an initial call to GetAdaptersAddresses to get
	// the necessary size into addrLen
	rc = GetAdaptersAddresses(AF_INET6, 0, 0, pAdapterAddresses, &addrLen);
	if (rc == ERROR_BUFFER_OVERFLOW) 
	{
		delete [] reinterpret_cast<char*>(pAdapterAddresses);
		pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[addrLen]);
	}
	else if (rc != ERROR_SUCCESS)
	{
		throw NetException("cannot get network adapter list");
	}
	try
	{
		if (GetAdaptersAddresses(AF_INET6, 0, 0, pAdapterAddresses, &addrLen) == NO_ERROR) 
		{
			pAddress = pAdapterAddresses;
			while (pAddress) 
			{
				if (pAddress->FirstUnicastAddress)
				{
					IPAddress addr(pAddress->FirstUnicastAddress->Address.lpSockaddr, pAddress->FirstUnicastAddress->Address.iSockaddrLength);
					result.push_back(NetworkInterface(std::string(pAddress->AdapterName), addr, pAddress->Ipv6IfIndex));
					pAddress = pAddress->Next;
				}
			}
		}
		else throw NetException("cannot get network adapter list");
	}
	catch (Poco::Exception&)
	{
		delete [] reinterpret_cast<char*>(pAdapterAddresses);
		throw;
	}
	delete [] reinterpret_cast<char*>(pAdapterAddresses);
#endif

	// Add IPv4 loopback interface (not returned by GetAdaptersInfo)
	result.push_back(NetworkInterface("Loopback", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1));
	// On Windows 2000 we use GetAdaptersInfo.
	PIP_ADAPTER_INFO pAdapterInfo;
	PIP_ADAPTER_INFO pInfo = 0;
	ULONG infoLen = sizeof(IP_ADAPTER_INFO);
	pAdapterInfo  = reinterpret_cast<IP_ADAPTER_INFO*>(new char[infoLen]);
	// Make an initial call to GetAdaptersInfo to get
	// the necessary size into infoLen
	rc = GetAdaptersInfo(pAdapterInfo, &infoLen);
	if (rc == ERROR_BUFFER_OVERFLOW) 
	{
		delete [] reinterpret_cast<char*>(pAdapterInfo);
		pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[infoLen]);
	}
	else if (rc != ERROR_SUCCESS)
	{
		throw NetException("cannot get network adapter list");
	}
	try
	{
		if (GetAdaptersInfo(pAdapterInfo, &infoLen) == NO_ERROR) 
		{
			pInfo = pAdapterInfo;
			while (pInfo) 
			{
				IPAddress address(std::string(pInfo->IpAddressList.IpAddress.String));
				if (!address.isWildcard()) // only return interfaces that have an address assigned.
				{
					IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String));
					IPAddress broadcastAddress(address);
					broadcastAddress.mask(subnetMask, IPAddress("255.255.255.255"));
					result.push_back(NetworkInterface(std::string(pInfo->AdapterName), address, subnetMask, broadcastAddress));
				}
				pInfo = pInfo->Next;
			}
		}
		else throw NetException("cannot get network adapter list");
	}
	catch (Poco::Exception&)
	{
		delete [] reinterpret_cast<char*>(pAdapterInfo);
		throw;
	}
	delete [] reinterpret_cast<char*>(pAdapterInfo);

	return result;
}


} } // namespace Poco::Net


#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
//
// BSD variants
//
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_dl.h>


namespace Poco {
namespace Net {


NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
	FastMutex::ScopedLock lock(_mutex);
	NetworkInterfaceList result;

	struct ifaddrs* ifaphead;
	int rc = getifaddrs(&ifaphead);
	if (rc) throw NetException("cannot get network adapter list");

	for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next) 
	{
		if (ifap->ifa_addr)
		{
			if (ifap->ifa_addr->sa_family == AF_INET)
			{
				IPAddress addr(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_addr)->sin_addr, sizeof(struct in_addr));
				result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr));
			}
#if defined(POCO_HAVE_IPv6)
			else if (ifap->ifa_addr->sa_family == AF_INET6)
			{
				IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
				result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr, if_nametoindex(ifap->ifa_name)));
			}
#endif
		}
	}
	freeifaddrs(ifaphead);
	return result;
}


} } // namespace Poco::Net


#elif POCO_OS == POCO_OS_LINUX
//
// Linux
//


namespace Poco {
namespace Net {


NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
	FastMutex::ScopedLock lock(_mutex);
	NetworkInterfaceList result;
	DatagramSocket socket;
	// the following code is loosely based
	// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
	int lastlen = 0;
	int len = 100*sizeof(struct ifreq);
	char* buf = 0;
	try
	{
		struct ifconf ifc;
		for (;;)
		{
			buf = new char[len];
			ifc.ifc_len = len;
			ifc.ifc_buf = buf;
			if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
			{
				if (errno != EINVAL || lastlen != 0)
					throw NetException("cannot get network adapter list");
			}
			else
			{
				if (ifc.ifc_len == lastlen)
					break;
				lastlen = ifc.ifc_len;
			}
			len += 10*sizeof(struct ifreq);
			delete [] buf;
		}
		for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
		{
			const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
			IPAddress addr;
			bool haveAddr = false;
			switch (ifr->ifr_addr.sa_family)
			{
#if defined(POCO_HAVE_IPv6)
			case AF_INET6:
				addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
				haveAddr = true;
				break;
#endif
			case AF_INET:
				addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
				haveAddr = true;
				break;
			default:
				break;
			}
			if (haveAddr)
			{
#if defined(POCO_HAVE_IPv6)
				int index = if_nametoindex(ifr->ifr_name);
#else
				int index = -1;
#endif
				result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
			}
			ptr += sizeof(struct ifreq);
		}
	}
	catch (...)
	{
		delete [] buf;
		throw;
	}
	delete [] buf;
	return result;
}


} } // namespace Poco::Net


#else
//
// Non-BSD Unix variants
//


namespace Poco {
namespace Net {


NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
	FastMutex::ScopedLock lock(_mutex);
	NetworkInterfaceList result;
	DatagramSocket socket;
	// the following code is loosely based
	// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
	int lastlen = 0;
	int len = 100*sizeof(struct ifreq);
	char* buf = 0;
	try
	{
		struct ifconf ifc;
		for (;;)
		{
			buf = new char[len];
			ifc.ifc_len = len;
			ifc.ifc_buf = buf;
			if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
			{
				if (errno != EINVAL || lastlen != 0)
					throw NetException("cannot get network adapter list");
			}
			else
			{
				if (ifc.ifc_len == lastlen)
					break;
				lastlen = ifc.ifc_len;
			}
			len += 10*sizeof(struct ifreq);
			delete [] buf;
		}
		for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
		{
			const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
#if defined(POCO_HAVE_SALEN)
			len = ifr->ifr_addr.sa_len;
			if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr);
#else
			len = sizeof(struct sockaddr);
#endif
			IPAddress addr;
			bool haveAddr = false;
			switch (ifr->ifr_addr.sa_family)
			{
#if defined(POCO_HAVE_IPv6)
			case AF_INET6:
				if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
				addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
				haveAddr = true;
				break;
#endif
			case AF_INET:
				if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
				addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
				haveAddr = true;
				break;
			default:
				break;
			}
			if (haveAddr)
			{
#if defined(POCO_HAVE_IPv6)
				int index = if_nametoindex(ifr->ifr_name);
#else
				int index = -1;
#endif
				result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
			}
			len += sizeof(ifr->ifr_name);
			ptr += len;
		}
	}
	catch (...)
	{
		delete [] buf;
		throw;
	}
	delete [] buf;
	return result;
}


} } // namespace Poco::Net


#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?