关于使用wxWidgets获取本机IP地址,MAC地址的问 Topic is solved

这是wxWidgets论坛的中文版本。在这里,您可以用您的母语汉语讨论上面任一子论坛所涉及的所有关于wxWidgets的话题。欢迎大家参与到对有价值的帖子的中英互译工作中来!
Post Reply
wonderli
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Feb 15, 2010 1:58 am
Location: Beijing,China

关于使用wxWidgets获取本机IP地址,MAC地址的问

Post by wonderli »

毕设要写一个跨平台程序,需要获取本机的IP和MAC地址,原文档设计的时候说是准备调用ifconfig或者ipconfig等系统原生程序然后进行提取,不过这样有个问题:不同机器的语言可能不一样,所以ifconfig或ipconfig的输出就不一样,处理起来可能会特别麻烦...
打算换种思路处理,想问下大家,wxWidgets 2.8.10的库的那些类可以实现这个功能?
我自己也尝试了用网上流传的通过wxWidgets的库获取IP地址的方法(源码在下面),不过它只返回本地环回的地址:127.0.1.1,wiki上貌似提到了这个问题,不过没看懂,囧...
想问下大家有什么建议,谢谢了~
源码如下:
#include<wx/socket.h>
int main()
{
wxIPV4address addr;
addr.Hostname(wxGetFullHostName());
wxString ipAddr = addr.IPAddress();
wxPuts(ipAddr);
}
Ubuntu 9.10 Linux
Gcc 4.4.1
wxWidgets 2.8.10
sishui
Earned some good credits
Earned some good credits
Posts: 121
Joined: Mon Mar 10, 2008 6:13 am
Location: 中國

Re: 关于使用wxWidgets获取本机IP地址,MAC地址的

Post by sishui »

wonderli wrote:毕设要写一个跨平台程序,需要获取本机的IP和MAC地址,原文档设计的时候说是准备调用ifconfig或者ipconfig等系统原生程序然后进行提取,不过这样有个问题:不同机器的语言可能不一样,所以ifconfig或ipconfig的输出就不一样,处理起来可能会特别麻烦...
打算换种思路处理,想问下大家,wxWidgets 2.8.10的库的那些类可以实现这个功能?
我自己也尝试了用网上流传的通过wxWidgets的库获取IP地址的方法(源码在下面),不过它只返回本地环回的地址:127.0.1.1,wiki上貌似提到了这个问题,不过没看懂,囧...
想问下大家有什么建议,谢谢了~
源码如下:
#include<wx/socket.h>
int main()
{
wxIPV4address addr;
addr.Hostname(wxGetFullHostName());
wxString ipAddr = addr.IPAddress();
wxPuts(ipAddr);
}

wxIPV4address ip;
wxString hostName = wxGetHostName();
ip.Hostname( hostName );

wxString ip_str = ip.IPAddress();
work work!!!
wonderli
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Feb 15, 2010 1:58 am
Location: Beijing,China

Re: 关于使用wxWidgets获取本机IP地址,MAC地址的

Post by wonderli »

sishui wrote:
wonderli wrote:毕设要写一个跨平台程序,需要获取本机的IP和MAC地址,原文档设计的时候说是准备调用ifconfig或者ipconfig等系统原生程序然后进行提取,不过这样有个问题:不同机器的语言可能不一样,所以ifconfig或ipconfig的输出就不一样,处理起来可能会特别麻烦...
打算换种思路处理,想问下大家,wxWidgets 2.8.10的库的那些类可以实现这个功能?
我自己也尝试了用网上流传的通过wxWidgets的库获取IP地址的方法(源码在下面),不过它只返回本地环回的地址:127.0.1.1,wiki上貌似提到了这个问题,不过没看懂,囧...
想问下大家有什么建议,谢谢了~
源码如下:
#include<wx/socket.h>
int main()
{
wxIPV4address addr;
addr.Hostname(wxGetFullHostName());
wxString ipAddr = addr.IPAddress();
wxPuts(ipAddr);
}

wxIPV4address ip;
wxString hostName = wxGetHostName();
ip.Hostname( hostName );

wxString ip_str = ip.IPAddress();
谢谢,这个方法我试了,不知道为什么总是返回255.255.255.255广播地址,很诡异...
Ubuntu 9.10 Linux
Gcc 4.4.1
wxWidgets 2.8.10
sishui
Earned some good credits
Earned some good credits
Posts: 121
Joined: Mon Mar 10, 2008 6:13 am
Location: 中國

Re: 关于使用wxWidgets获取本机IP地址,MAC地址的

Post by sishui »

wonderli wrote:
sishui wrote:
wonderli wrote:毕设要写一个跨平台程序,需要获取本机的IP和MAC地址,原文档设计的时候说是准备调用ifconfig或者ipconfig等系统原生程序然后进行提取,不过这样有个问题:不同机器的语言可能不一样,所以ifconfig或ipconfig的输出就不一样,处理起来可能会特别麻烦...
打算换种思路处理,想问下大家,wxWidgets 2.8.10的库的那些类可以实现这个功能?
我自己也尝试了用网上流传的通过wxWidgets的库获取IP地址的方法(源码在下面),不过它只返回本地环回的地址:127.0.1.1,wiki上貌似提到了这个问题,不过没看懂,囧...
想问下大家有什么建议,谢谢了~
源码如下:
#include<wx/socket.h>
int main()
{
wxIPV4address addr;
addr.Hostname(wxGetFullHostName());
wxString ipAddr = addr.IPAddress();
wxPuts(ipAddr);
}

wxIPV4address ip;
wxString hostName = wxGetHostName();
ip.Hostname( hostName );

wxString ip_str = ip.IPAddress();
谢谢,这个方法我试了,不知道为什么总是返回255.255.255.255广播地址,很诡异...
这是获取的lan网IP。
请检查你的ip地址,是否设置,或者DHCP是否分配上。如果没有IP,返回的是127.0.0.1。
具体你返回广播地址这种情况,那我的确没遇到过,你跟踪调试看看
我才试了没问题。
work work!!!
kingkamg
I live to help wx-kind
I live to help wx-kind
Posts: 187
Joined: Tue Apr 08, 2008 1:45 pm

Post by kingkamg »

class wxMACAddressUtility
{

public:
static wxString GetMACAddress()
{
unsigned char result[6];
if(GetMACAddress(result) == 0)
{
return wxString::Format(wxT("%02X:%02X:%02X:%02X:%02X:%02X"),
(unsigned int)result[0], (unsigned int)result[1], (unsigned int)result[2],
(unsigned int)result[3], (unsigned int)result[4], (unsigned int)result[5]);
}
return wxEmptyString;
}

private:
static long GetMACAddress(unsigned char * result);

#if defined(WIN32) || defined(UNDER_CE)
static long GetMACAddressMSW(unsigned char * result);
#elif defined(__APPLE__)
static long GetMACAddressMAC(unsigned char * result);
#elif defined(LINUX) || defined(linux)
static long GetMACAddressLinux(unsigned char * result);
#endif
};
wonderli
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Feb 15, 2010 1:58 am
Location: Beijing,China

Re: 关于使用wxWidgets获取本机IP地址,MAC地址的

Post by wonderli »

sishui wrote:
wonderli wrote:
sishui wrote:
wxIPV4address ip;
wxString hostName = wxGetHostName();
ip.Hostname( hostName );

wxString ip_str = ip.IPAddress();
谢谢,这个方法我试了,不知道为什么总是返回255.255.255.255广播地址,很诡异...
这是获取的lan网IP。
请检查你的ip地址,是否设置,或者DHCP是否分配上。如果没有IP,返回的是127.0.0.1。
具体你返回广播地址这种情况,那我的确没遇到过,你跟踪调试看看
我才试了没问题。
我又查了一下自己的机器,可能这东西跟系统的Hosts有关
当我机器的hosts是这样时:
127.0.0.1 localhost
返回的地址是255.255.255.255
当我的机器的hosts是默认的这样时:
127.0.0.1 localhost
127.0.1.1 lixinyu-laptop
返回的地址就是那个127.0.0.1
但是我ifconfig输出的信息是这样的:
eth0 Link encap:Ethernet HWaddr 00:16:d3:a4:e7:c0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:17

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:440 (440.0 B) TX bytes:440 (440.0 B)

ppp0 Link encap:Point-to-Point Protocol
inet addr:116.69.223.211 P-t-P:115.168.64.99 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1448 Metric:1
RX packets:8700 errors:8 dropped:0 overruns:0 frame:0
TX packets:9820 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:4876908 (4.8 MB) TX bytes:6316790 (6.3 MB)
的确是有公网IP的,搞不懂了。。。不知道为啥这样子。。。
Ubuntu 9.10 Linux
Gcc 4.4.1
wxWidgets 2.8.10
wonderli
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Feb 15, 2010 1:58 am
Location: Beijing,China

Post by wonderli »

kingkamg wrote:class wxMACAddressUtility
{

public:
static wxString GetMACAddress()
{
unsigned char result[6];
if(GetMACAddress(result) == 0)
{
return wxString::Format(wxT("%02X:%02X:%02X:%02X:%02X:%02X"),
(unsigned int)result[0], (unsigned int)result[1], (unsigned int)result[2],
(unsigned int)result[3], (unsigned int)result[4], (unsigned int)result[5]);
}
return wxEmptyString;
}

private:
static long GetMACAddress(unsigned char * result);

#if defined(WIN32) || defined(UNDER_CE)
static long GetMACAddressMSW(unsigned char * result);
#elif defined(__APPLE__)
static long GetMACAddressMAC(unsigned char * result);
#elif defined(LINUX) || defined(linux)
static long GetMACAddressLinux(unsigned char * result);
#endif
};
多谢这个MAC地址解决方案,准备试一下~
Ubuntu 9.10 Linux
Gcc 4.4.1
wxWidgets 2.8.10
kingkamg
I live to help wx-kind
I live to help wx-kind
Posts: 187
Joined: Tue Apr 08, 2008 1:45 pm

Post by kingkamg »

:D :D 这下不用试了吧,给你实现类

Code: Select all

#include "stdwx.h"
#include "wxMACAddressUtility.h"

#include <stdio.h>

#if defined(WIN32) || defined(UNDER_CE)
#	include <windows.h>
#	if defined(UNDER_CE)
#		include <Iphlpapi.h>
#	endif
#elif defined(__APPLE__)
#	include <CoreFoundation/CoreFoundation.h>
#	include <IOKit/IOKitLib.h>
#	include <IOKit/network/IOEthernetInterface.h>
#	include <IOKit/network/IONetworkInterface.h>
#	include <IOKit/network/IOEthernetController.h>
#elif defined(LINUX) || defined(linux)
#	include <string.h>
#	include <net/if.h>
#	include <sys/ioctl.h>
#   include <sys/socket.h>
#   include <arpa/inet.h>
#endif

long wxMACAddressUtility::GetMACAddress(unsigned char * result)
{
	// Fill result with zeroes
	memset(result, 0, 6);
	// Call appropriate function for each platform
#if defined(WIN32) || defined(UNDER_CE)
	return GetMACAddressMSW(result);
#elif defined(__APPLE__)
	return GetMACAddressMAC(result);
#elif defined(LINUX) || defined(linux)
	return GetMACAddressLinux(result);
#endif
	// If platform is not supported then return error code
	return -1;
}

#if defined(WIN32) || defined(UNDER_CE)

inline long wxMACAddressUtility::GetMACAddressMSW(unsigned char * result)
{

#if defined(UNDER_CE)
	IP_ADAPTER_INFO AdapterInfo[16]; // Allocate information
	DWORD dwBufLen = sizeof(AdapterInfo); // Save memory size of buffer
	if(GetAdaptersInfo(AdapterInfo, &dwBufLen) == ERROR_SUCCESS) 
	{
		memcpy(result, AdapterInfo->Address, 6);
	}
	else return -1;
#else
	UUID uuid;
	if(UuidCreateSequential(&uuid) == RPC_S_UUID_NO_ADDRESS) return -1;
	memcpy(result, (char*)(uuid.Data4+2), 6);
#endif
	return 0;
}

#elif defined(__APPLE__)

static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices)
{
	kern_return_t		kernResult;
	CFMutableDictionaryRef	matchingDict;
	CFMutableDictionaryRef	propertyMatchDict;

	matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);

	if (NULL != matchingDict)
	{
		propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
			&kCFTypeDictionaryKeyCallBacks,
			&kCFTypeDictionaryValueCallBacks);

		if (NULL != propertyMatchDict)
		{
			CFDictionarySetValue(propertyMatchDict, CFSTR(kIOPrimaryInterface), kCFBooleanTrue);
			CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
			CFRelease(propertyMatchDict);
		}
	}
	kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices);
	return kernResult;
}

static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize)
{
	io_object_t		intfService;
	io_object_t		controllerService;
	kern_return_t	kernResult = KERN_FAILURE;

	if (bufferSize < kIOEthernetAddressSize) {
		return kernResult;
	}

	bzero(MACAddress, bufferSize);

	while (intfService = IOIteratorNext(intfIterator))
	{
		CFTypeRef	MACAddressAsCFData;        

		// IONetworkControllers can't be found directly by the IOServiceGetMatchingServices call, 
		// since they are hardware nubs and do not participate in driver matching. In other words,
		// registerService() is never called on them. So we've found the IONetworkInterface and will 
		// get its parent controller by asking for it specifically.

		// IORegistryEntryGetParentEntry retains the returned object, so release it when we're done with it.
		kernResult = IORegistryEntryGetParentEntry(intfService,
			kIOServicePlane,
			&controllerService);

		if (KERN_SUCCESS != kernResult) {
			printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kernResult);
		}
		else {
			// Retrieve the MAC address property from the I/O Registry in the form of a CFData
			MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
				CFSTR(kIOMACAddress),
				kCFAllocatorDefault,
				0);
			if (MACAddressAsCFData) {
				CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr

				// Get the raw bytes of the MAC address from the CFData
				CFDataGetBytes((CFDataRef)MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
				CFRelease(MACAddressAsCFData);
			}

			// Done with the parent Ethernet controller object so we release it.
			(void) IOObjectRelease(controllerService);
		}

		// Done with the Ethernet interface object so we release it.
		(void) IOObjectRelease(intfService);
	}

	return kernResult;
}

long wxMACAddressUtility::GetMACAddressMAC(unsigned char * result)
{
	io_iterator_t	intfIterator;
	kern_return_t	kernResult = KERN_FAILURE;
	do
	{
		kernResult = ::FindEthernetInterfaces(&intfIterator);
		if (KERN_SUCCESS != kernResult) break;
		kernResult = ::GetMACAddress(intfIterator, (UInt8*)result, 6);
	}
	while(false);
	(void) IOObjectRelease(intfIterator);
}

#elif defined(LINUX) || defined(linux)

long wxMACAddressUtility::GetMACAddressLinux(unsigned char * result)
{
	struct ifreq ifr;
	struct ifreq *IFR;
	struct ifconf ifc;
	char buf[1024];
	int s, i;
	int ok = 0;

	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1)
	{
		return -1;
	}

	ifc.ifc_len = sizeof(buf);
	ifc.ifc_buf = buf;
	ioctl(s, SIOCGIFCONF, &ifc);

	IFR = ifc.ifc_req;
	for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++)
	{
		strcpy(ifr.ifr_name, IFR->ifr_name);
		if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
		{
			if (! (ifr.ifr_flags & IFF_LOOPBACK))
			{
				if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0)
				{
					ok = 1;
					break;
				}
			}
		}
	}

	shutdown(s, SHUT_RDWR);
	if (ok)
	{
		bcopy( ifr.ifr_hwaddr.sa_data, result, 6);
	}
	else
	{
		return -1;
	}
	return 0;
}

#endif
Post Reply