getsockname和gethostname都能擷取IP地址,但是還是有卻別的:
- getsockname: 是擷取跟某一特定的socket相關的IP地址。
- gethostname: 是擷取原生所有的IP地址。
先來看下他們的擷取Ip地址的方式。
- getsockname方式:
sockaddr_in test;
int len = sizeof(test);
if ( 0 == getsockname( m_socket, ( struct sockaddr* )&test, &len ))
{
char *pIPAddr = inet_ntoa(test.sin_addr);
}
這裡假設m_socket是一個有效通訊端。
上面代碼中pIPAddr就是想要擷取的IP地址。
- gethostname方式:
TCHAR host[255];
host[0]= 0;
gethostname (host, 255);
struct hostent FAR * pp;
pp = gethostbyname (host);
int i = 0;
while ( pp->h_addr_list[i++] != NULL)
{
struct in_addr in;
in.s_addr = *((DWORD*)(&pp->h_addr_list[i][0]));
char *pAddr = inet_ntoa(in);
cout<<pAddr<<endl;
}
上面代碼中pAddr就是擷取的IP地址。
其實gethostname對應的這段代碼的效果和你在命令視窗中執行ipconfig /all效果是一樣的。
gethostname你只要初始化了winsock庫就可以直接使用上述代碼得到原生IP了(在linux中不需要,直接用)。但是getsockname方式來擷取對應的IP地址的時候,首先需要通過socket函數建立的有效通訊端,另外還要bind。才能執行成功。如果在socket和bind之間調用就會調用失敗。雖然在bind之後可以執行成功,通常我們得到的結果是0.0.0.0,除非在bind的時候就指定特定的IP。好先給一段簡單的代碼。
SOCKET socket1;
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData))
{
printf("Winsock can not be init!");
WSACleanup();
return 0;
}
printf("server begin to create socket!/n");
//struct sockaddr_in local;
//struct sockaddr_in from;
sockaddr_in local;
sockaddr_in from;
int fromlen = sizeof(from);
local.sin_addr.s_addr = /*inet_addr( "192.168.200.141" );//*/INADDR_ANY;
local.sin_family = AF_INET;
local.sin_port = htons(9101);
socket1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if ( INVALID_SOCKET == socket1 )
{
printf( "failed to create socket" );
WSACleanup();
return 1;
}
if ( SOCKET_ERROR == bind(socket1, (struct sockaddr *)&local, fromlen))
{
printf( "failed to bind port" );
DWORD dw = GetLastError();
WSACleanup();
return 1;
}
//////////////////////////////////////////////////////////////////////////
sockaddr_in test1;
int len1 = sizeof(test1);
if ( 0 == getsockname( socket1, ( struct sockaddr* )&test1, &len1 ))
{
char *pTem1 = inet_ntoa(test1.sin_addr);
}
執行上面代碼就會發現pTem1的值是0.0.0.0 。 如果我們把上述代碼中的加粗的那行代碼中的INADDR_ANY換成前面的
inet_addr( "192.168.200.141" ); 再一次執行代碼就會發現pTem1的值是192.168.200.141。也許有人會問你不是在bind的時候知道自己綁定的是那個ip嗎(一個可能有多個網卡),何必多此一舉的去在調用api來擷取呢?我這裡這樣列出只是為了說明問題,而實際的應用你根本不知道你拿到的socket對應的IP是多少你就可以通過這種方式來擷取了。 上面列出的是基於資料報的UDP的情形,其實基於流式通訊端的TCP是同樣的效果。 上面的結論都在windows xp上面vc6下面測試得出。下面再綴一點擷取本機IP地址的方法,為什麼說是綴,因為不是很相關.如果想擷取本機所有網卡的資訊,當然也包括IP的資訊。可以通過GetAdaptersInfo這個windows API。區別於上述方法的是,這個函數只能在windows上面,前面兩個在windows和linux上面都可以。 下面列出用該方法的執行個體代碼:未完待續...