Get public IP with winsock

Started by Alessio, April 12, 2008, 02:20:10 PM

Previous topic - Next topic

Alessio


//
// get public ip
//
// by Alessio Ribeca <e-mail: peloquin at libero dot it>
//
// 11 aprile 2008
//

//
#define STRICT
#define WIN32_MEAN_AND_LEAN

//
#include <winsock.h>

//
#define __WINSOCK_VERSION__ 1
#define __RETRY__ 10
#define __SITE__ "www.ip-adress.com"

//
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "wsock32.lib")

//
static LPCSTR szAppName = "MyIP";
static LPCSTR szGetIP = "GET / HTTP/1.1\r\n"
"Host: "__SITE__"\r\n"
"\r\n";

//
inline void find_string(char * string, char * pattern, char buffer[], int iBuffer, char c)
{
ZeroMemory(buffer, iBuffer);

char *pos = strstr(string, pattern);

if ( NULL == pos )
{
//
buffer[0] = '\0';

return;
}

int i = 0;

pos += strlen(pattern);

while ( *pos != c )
{
buffer[i] = *pos;
++pos;
++i;

if ( i > iBuffer )
{
buffer[0] = '\0';
return;
}
}
}


//
LPSTR GetIP(VOID)
{
WSADATA wsaData;

if ( 0 != WSAStartup(MAKEWORD(__WINSOCK_VERSION__,0), &wsaData) )
{
return "unable to start winsock";
}

//
if ( LOBYTE(wsaData.wVersion) < __WINSOCK_VERSION__ )
{
WSACleanup();

return "unable to start winsock";
}

//
LPHOSTENT lpHostent = gethostbyname(__SITE__);
if ( NULL == lpHostent )
{
WSACleanup();

return "gethostbyname() failed";
}

//
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( INVALID_SOCKET == s)
{
WSACleanup();

return "socket error";
}

// fill sockadd structure
struct sockaddr_in sa = { 0 };
sa.sin_addr.s_addr = inet_addr(inet_ntoa (*(struct in_addr *)*lpHostent->h_addr_list));
sa.sin_family = AF_INET;
sa.sin_port = htons(80);

//
INT iRetry = 0;
while ( connect(s, (SOCKADDR*)&sa, sizeof(sa)) == SOCKET_ERROR )
{
if ( ++iRetry > __RETRY__ )
{
WSACleanup();

return "unable to connect";
}
}

//
if ( SOCKET_ERROR == send(s, szGetIP, lstrlen(szGetIP), 0) )
{
WSACleanup();

return "send error";
}

// recv
char buffer[2048] = { 0 };
if ( recv (s, buffer, 2048, 0) == SOCKET_ERROR )
{
WSACleanup();

return "recv error";
}

CHAR szIp[16];
CHAR szLocation[64];
CHAR szLatitude[16];
CHAR szLongitude[16];
CHAR szIsp[64];

find_string(buffer, "My IP: ", szIp, 16, '<');
find_string(buffer, "IP Location: ", szLocation, 64, '<');
find_string(buffer, "Latitude: ", szLatitude, 16, '<');
find_string(buffer, "Longitude: ", szLongitude, 16, '<');
find_string(buffer, "My ISP: ", szIsp, 64, '<');

static CHAR szBuffer[256];
ZeroMemory(&szBuffer, 256);

wsprintf(szBuffer, "IP: %s\nLocation: %s\nLatitude: %s\nLongitude: %s\nISP: %s", szIp, szLocation, szLatitude, szLongitude, szIsp);

WSACleanup();

return szBuffer;
}

//
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, INT iCmdShow)
{
MessageBox(NULL, GetIP(), szAppName, MB_ICONINFORMATION);

return 0;
}


Vortex

Hi Alessio,

Thanks for the example. It works fine on my Win XP Pro Sp2 box.
Code it... That's all...

CLR

Hello Alessio.

I got nothing. Here's output:


FILE *fp;
fp = fopen("ip.txt", "wb");
fwrite(buffer, sizeof(buffer), 1, fp);
fclose(fp);


Alessio

Hi CLR,

simply use more space for buffer variable.
Change recv buffer from 2048 to 4096.

// recv
char buffer[4096] = { 0 };
if ( recv (s, buffer, 4096, 0) == SOCKET_ERROR )
{
WSACleanup();

return "recv error";
}



CLR

Hello Alessio. Thanks.

For some reason changing from 2048 to 4096 didn't work. Another recv dit

char buffer[4096] = { 0 };
if ( recv (s, buffer, 4096, 0) == SOCKET_ERROR )
{
WSACleanup();

return "recv error";
}

[b]recv (s, buffer, 4096, 0);[/b]

Alessio

pls save to file buffer output and attach it!
Otherwise look for specified string like "My IP: " or "IP Location: "

thank you.

CLR

Hi Alessio.

I'm back. Please see the attachment. Thanks!

Alessio

Hi,

as you can see, you ip appear on file named ip2.txt, where appears next 4096 bytes of ip1.txt.
I don't know why your buffer is not large enough, but if you try a more big buffer, you'll success.
Try with 8192, 16304 or more.

Bye, Alessio.