#include <list>
#include <winsock2.h>
#include <winsock.h>
#pragma comment(lib,"ws2_32.lib");
typedef unsigned int uint32_t;
#define RTPUDPV4TRANS_IFREQBUFSIZE 8192
std::list<uint32_t> localIPs;
一、通过网络信息
bool GetLocalIPList_Interfaces()
{
unsigned char buffer[RTPUDPV4TRANS_IFREQBUFSIZE];
DWORD outputsize;
DWORD numaddresses,i;
SOCKET_ADDRESS_LIST *addrlist;
SOCKET rtpsock;
rtpsock = socket(PF_INET,SOCK_DGRAM,0);
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(9090);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(rtpsock,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
closesocket(rtpsock);
return false;
}
if (WSAIoctl(rtpsock,SIO_ADDRESS_LIST_QUERY,NULL,0,&buffer,RTPUDPV4TRANS_IFREQBUFSIZE,&outputsize,NULL,NULL))
return false;
addrlist = (SOCKET_ADDRESS_LIST *)buffer;
numaddresses = addrlist->iAddressCount;
for (i = 0 ; i < numaddresses ; i++)
{
SOCKET_ADDRESS *sockaddr = &(addrlist->Address[i]);
if (sockaddr->iSockaddrLength == sizeof(struct sockaddr_in)) // IPv4 address
{
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr->lpSockaddr;
localIPs.push_back(ntohl(addr->sin_addr.s_addr));
}
}
if (localIPs.empty())
return false;
return true;
}
二、通过DNS信息(若上面方法失败再使用此方法)
void GetLocalIPList_DNS()
{
struct hostent *he;
char name[1024];
uint32_t ip;
bool done;
int i,j;
gethostname(name,1023);
name[1023] = 0;
he = gethostbyname(name);
if (he == 0)
return;
ip = 0;
i = 0;
done = false;
while (!done)
{
if (he->h_addr_list[i] == NULL)
done = true;
else
{
ip = 0;
for (j = 0 ; j < 4 ; j++)
ip |= ((uint32_t)((unsigned char)he->h_addr_list[i][j])<<((3-j)*8));
localIPs.push_back(ip);
i++;
}
}
}
三、使用上面方法获取列表后还要再添加本地回送地址
void AddLoopbackAddress()
{
uint32_t loopbackaddr = (((uint32_t)127)<<24)|((uint32_t)1);
std::list<uint32_t>::const_iterator it;
bool found = false;
for (it = localIPs.begin() ; !found && it != localIPs.end() ; it++)
{
if (*it == loopbackaddr)
found = true;
}
if (!found)
localIPs.push_back(loopbackaddr);
}
四、综合
int CreateLocalIPList()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return false;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return false;
}
// first try to obtain the list from the network interface info
if (!GetLocalIPList_Interfaces())
{
// If this fails, we'll have to depend on DNS info
GetLocalIPList_DNS();
}
AddLoopbackAddress();
WSACleanup();
return 0;
}
参考jrtp库中的rtpudpv4transmitter.cpp
// test_ip.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <list>
#include <winsock2.h>
#include <winsock.h>
//#pragma comment(lib, "ws32_2.lib")
#pragma comment(lib,"ws2_32.lib");
//#pragma comment(lib, "win32.lib")
typedef unsigned int uint32_t;
#define RTPUDPV4TRANS_IFREQBUFSIZE 8192
std::list<uint32_t> localIPs;
bool GetLocalIPList_Interfaces()
{
unsigned char buffer[RTPUDPV4TRANS_IFREQBUFSIZE];
DWORD outputsize;
DWORD numaddresses,i;
SOCKET_ADDRESS_LIST *addrlist;
SOCKET rtpsock;
rtpsock = socket(PF_INET,SOCK_DGRAM,0);
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(9090);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(rtpsock,(struct sockaddr *)&addr,sizeof(struct sockaddr_in)) != 0)
{
closesocket(rtpsock);
return false;
}
if (WSAIoctl(rtpsock,SIO_ADDRESS_LIST_QUERY,NULL,0,&buffer,RTPUDPV4TRANS_IFREQBUFSIZE,&outputsize,NULL,NULL))
return false;
addrlist = (SOCKET_ADDRESS_LIST *)buffer;
numaddresses = addrlist->iAddressCount;
for (i = 0 ; i < numaddresses ; i++)
{
SOCKET_ADDRESS *sockaddr = &(addrlist->Address[i]);
if (sockaddr->iSockaddrLength == sizeof(struct sockaddr_in)) // IPv4 address
{
struct sockaddr_in *addr = (struct sockaddr_in *)sockaddr->lpSockaddr;
localIPs.push_back(ntohl(addr->sin_addr.s_addr));
}
}
if (localIPs.empty())
return false;
return true;
}
void GetLocalIPList_DNS()
{
struct hostent *he;
char name[1024];
uint32_t ip;
bool done;
int i,j;
gethostname(name,1023);
name[1023] = 0;
he = gethostbyname(name);
if (he == 0)
return;
ip = 0;
i = 0;
done = false;
while (!done)
{
if (he->h_addr_list[i] == NULL)
done = true;
else
{
ip = 0;
for (j = 0 ; j < 4 ; j++)
ip |= ((uint32_t)((unsigned char)he->h_addr_list[i][j])<<((3-j)*8));
localIPs.push_back(ip);
i++;
}
}
}
void AddLoopbackAddress()
{
uint32_t loopbackaddr = (((uint32_t)127)<<24)|((uint32_t)1);
std::list<uint32_t>::const_iterator it;
bool found = false;
for (it = localIPs.begin() ; !found && it != localIPs.end() ; it++)
{
if (*it == loopbackaddr)
found = true;
}
if (!found)
localIPs.push_back(loopbackaddr);
}
int CreateLocalIPList()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return false;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return false;
}
// first try to obtain the list from the network interface info
if (!GetLocalIPList_Interfaces())
{
// If this fails, we'll have to depend on DNS info
GetLocalIPList_DNS();
}
AddLoopbackAddress();
WSACleanup();
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
CreateLocalIPList();
printf("ip testing...\n");
getchar();
return 0;
}