Узнать IP на C++

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by agrofyl2, 6 Aug 2009.

  1. agrofyl2

    agrofyl2 New Member

    Joined:
    25 Apr 2008
    Messages:
    54
    Likes Received:
    4
    Reputations:
    0
    При тестировании моего тр... в общем моей программы, у меня возникла проблема: нужно было определить айпи-адрес клиента.
    Определяю я его так:
    Code:
    //Получиние своего IP
    void GetCurrentIP(char *host) {
    	WSADATA wsaData;
    	WSAStartup(MAKEWORD(2,2), &wsaData);// инициализируем socket'ы используя Ws2_32.dll для процесса
    	char HostName[1024]; // создаем буфер для имени хоста    
    	if(!gethostname(HostName, 1024)) // получаем имя хоста  
    	{
    		if(LPHOSTENT lphost = gethostbyname(HostName)) // получаем IP хоста, т.е. нашего компа
    			strcpy(host,inet_ntoa(*((in_addr*)lphost->h_addr_list[0]))); // преобразуем переменную типа LPIN_ADDR в DWORD    
    	}    
    	WSACleanup();
    }
    
    Определять то он определяет, НО! при тесте обнаружилось, что, например, если у клиента АДСЛ, то он выдает 198.168.0.12 а не внешний айпи, как если бы у клиента был диалап.

    Можно ли как-нибудь определить внешний адрес методами С++, не прибегая к стороннему серверу(я конечно могу заставить его подконнектится к моему скрипту, опр. айпишник, или, например, спарсить его с 2ip.ru, но это, как мне кажется, изврат).

    Или, например, если заставить его приконнектится к опр.(моему) IP, а самому принять этот коннект, то как тогда определить адрес?
     
  2. __mad

    __mad Elder - Старейшина

    Joined:
    4 Nov 2007
    Messages:
    100
    Likes Received:
    38
    Reputations:
    7
    Если клиент за натом/роутером, то узнать реальный IP кроме как через внешний сервер - никак.

    Да, и нету тут никакого изврата в парсе IP через внешний сервер.

    Для того что бы узнать IP того кто к тебе приконектился смотри 2 переменную в функции accept, а точней поле sin_addr.s_addr в структуре addr.
     
    1 person likes this.
  3. altblitz

    altblitz Elder - Старейшина

    Joined:
    5 Jun 2009
    Messages:
    3,697
    Likes Received:
    3,139
    Reputations:
    236
    agrofyl2,
    вопрос интересный.

    пока не задумывался особо, не было в том нужды.
    но похоже внешний адрес рутера придется определять сторонними методами.

    по крайней мере, в ОС не видел реального своего АйПи, лишь 192.* (Вай-Фай)
     
    #3 altblitz, 6 Aug 2009
    Last edited: 6 Aug 2009
  4. mr.The

    mr.The Elder - Старейшина

    Joined:
    30 Apr 2007
    Messages:
    1,080
    Likes Received:
    456
    Reputations:
    38
    тс, делаеш запрос на сайт типа _ttp://www.whatismyip.com/ и регуляркой выдираеш реальный ip. можно не регуляркой, тогда через жопу, но напорядок меньше весит. в любом случае - элементарно пишется. либо можно ещё проще - сделать страницу на фрихосте, которая будет говорить ip. тогда вообще просто
     
  5. agrofyl2

    agrofyl2 New Member

    Joined:
    25 Apr 2008
    Messages:
    54
    Likes Received:
    4
    Reputations:
    0
    Итак, все получилось.
    У меня уже была написана команда, по которой клиент коннектится к опр. IP. И я получаю его IP как говорил __mad:

    Code:
    #include "iostream"
    using namespace std;
    
    #include <winsock2.h>
    #pragma comment( lib, "ws2_32.lib" )
    
    int port=2121;
    
    int main() {
    	cout << "Work" << endl;
    	WSADATA wsd;
    	if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
    		cout << "WSAData initialize error" << endl;
    		return 0;
    	}
    	
    	SOCKET sClient, sServer;
        struct sockaddr_in localaddr, clientaddr;
        int iSize;
    
    	sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
       
    	if (sServer == SOCKET_ERROR)
        {
    		cout << "Soket error" << endl;
            return 0;
        }
        localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        localaddr.sin_family = AF_INET;
        localaddr.sin_port = htons(port);
    
        if (bind(sServer, (struct sockaddr *)&localaddr, sizeof(localaddr)) == SOCKET_ERROR)
        {
    		cout << "Can't bind" << endl;
            return 1;
        }
        
        cout << "Bind OK" << endl;
    
        listen(sServer, 4);
    
        cout << "Listen OK" << endl;
    	
    	while(1) {
            iSize = sizeof(clientaddr);
            sClient = accept(sServer, (struct sockaddr *)&clientaddr, &iSize);
    		if (sClient == INVALID_SOCKET)
            {        
    			cout << "Accept filed" << endl;
                break;
            }
    		cout << "Accept OK" << endl;
    		cout << "Client IP: " << inet_ntoa(clientaddr.sin_addr) << endl;
                            //return 0;
    	}
        closesocket(sServer);
    	cout << "End" << endl;
    	WSACleanup();
        return 0;
    }
    
    Еще не тестил(только локалхост), но думаю работает.
    __mad'у спасибо!!! и вообще всем кто ответил