Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] узнать свой ip


Автор: CompWorm 8.6.2010, 21:01
Доброго времени!

задача: вывести свой локальный и внешний IP адрес.

я нашёл вот такой подход
Код

    QString ipAddress ="";
    QHostInfo info = QHostInfo::fromName( QHostInfo::localHostName() );
    QList<QHostAddress> listAddr= info.addresses();
    for( int i = 0; i < listAddr.size(); i ++ )
    {
        if( listAddr.at(i).protocol() == QAbstractSocket::IPv4Protocol )
        {
        ipAddress += " | ";
        ipAddress += listAddr.at(i).toString();
        }
    }

у меня нет внешнего IP - на выходе получаю 2 неадекватных айпишника.
дал прогу товарищу, у которого внешний ИП, по его словам, есть - на выходе всего один локальный ип... 

Автор: SABROG 9.6.2010, 09:08
Судя по тому, что написано в документации:

Цитата

QList<QHostAddress> QHostInfo::addresses () const
Returns the list of IP addresses associated with hostName()


Я могу предположить, что у Вас нет доменного имени привязанного к внешнему статическому IP адресу. Предположим, что Вы захотели поднять свой сайт, настроили Web сервер и прочее. Всё работает на локальной машине, но из интернета на него можно зайти только по IP адресу. Для этого арендуют свободное доменное имя за 20$ в год. Или пользуются бесплатными сервисами типа no-ip.com.

В Вашем случае, скорее всего, QHostInfo обращается к DNS серверу провайдера где пытается найти IP адрес на имя вашего локального компьютера и находит совершенно чужие компьютеры с таким именем в интернете.

Для Ваших целей должен подойти класс QNetworkInterface вместо QHostInfo.

Автор: CompWorm 9.6.2010, 10:56
я попробовал ваш вариант. теже яйца - вид сбоку. локальный ИП показывает хоршо, внешнего нет.

проблема оказалась суровей, чем я думал, а именно в том, что внешний ИП даётся провайдером, и далее сам провайдер от внешнего ИПа к моему компу прокладывает VPN... то есть на интерфейсе внешнего ИПа быть не может. как-то примерно так, но я могу ошибаться, ибо у меня внешнего вообще никогда не было  smile хз как там работеат

я вот обратил внимание, что qutIM при передаче файлов IP отправителя пишет тоже локальный, типа 192.168.yyy.xxx - там такую же ошибку допустили авторы.

самый банальный метод - закэпчить ИП с сайта, например так
http://www.whatismyip.com/automation/n09230945.asp
но может есть программный метод?

Автор: SABROG 9.6.2010, 11:14
Цитата(CompWorm @  9.6.2010,  10:56 Найти цитируемый пост)
но может есть программный метод? 

Роутер провайдера это чужой компьютер с двумя интерфейсами, один из которых играет роль твоего внешнего IP, но под этим адресом может сидеть вся сетка. Есть 3 способа узнать свой внешний IP:
- соединиться с внешним компьютером находящимся в интернете и попросить тебе передать адрес обратно.
- купить/узнать статический адрес у провайдера (соответственно в этом случае программные средства вообще не понадобятся)
- использовать dyndns и резолвить по dns имени внешний IP адрес

Для пользователей программы подходит только первый способ. Это значит нужно выделать отдельный сервер для этих целей или использовать чужие, но в этом случае нет никакой гарантии, что сервер завтра не закроется.

У меня например стоит роутер дома и для ноута или десктопа его внешний IP равен локальному IP адресу в локальной сети.

Автор: CompWorm 9.6.2010, 11:57
Цитата(SABROG @  9.6.2010,  11:14 Найти цитируемый пост)
Для пользователей программы подходит только первый способ. 

то есть так
Цитата(CompWorm @  9.6.2010,  10:56 Найти цитируемый пост)
самый банальный метод - закэпчить ИП с сайта, например так
http://www.whatismyip.com/automation/n09230945.asp

пока сервер не упадёт или не внесёт изменения...
хорошо, тогда первым кодом я вытягиваю локальный IP, а внешний тогда пробую так:
Код

    QNetworkRequest request;
    request.setUrl(QUrl("http://www.whatismyip.com/automation/n09230945.asp"));
    QNetworkReply *reply =networkManager.get(QNetworkRequest(request));
    while (!reply->isFinished())
    {
        ui->statusBar1->showMessage("waiting...");
    }
    ui->statusBar1->showMessage(reply->readLine());

но isFinished не наступает... вариант с сигналом 
Код

connect(&networkManager, SIGNAL(finished(QNetworkReply*)),
                 this, SLOT(on_nwkDownload_Finished(QNetworkReply*)));

работает, но мне надо IP получить сразу до выполнения следующей строчки кода. подскажить, в чём косяк.

Автор: SABROG 9.6.2010, 12:21
Цитата(CompWorm @  9.6.2010,  11:57 Найти цитируемый пост)
работает, но мне надо IP получить сразу до выполнения следующей строчки кода. подскажить, в чём косяк. 

Вынеси следующую строчку кода в отдельный слот или метод. Или не красивый и не правильный вариант:

Код

    QNetworkRequest request;
    request.setUrl(QUrl("http://www.whatismyip.com/automation/n09230945.asp"));
    QNetworkReply *reply =networkManager.get(QNetworkRequest(request));
    ui->statusBar1->showMessage("waiting...");
    QEventLoop loop;
    connect(&networkManager, SIGNAL(finished(QNetworkReply*)),
                 &loop, SLOT(quit()));
    loop.exec();
    ui->statusBar1->showMessage(reply->readLine());

Автор: CompWorm 9.6.2010, 12:43
SABROG, кроме того что с QEventLoop не красиво, в чём может крыться опасность? в чём "неправильность?" 
я так понял, она запускает отдельный поток, в котором ждёт сигнала quit, а вызывающее приложение ждёт окончания вызова exec()...
Цитата

To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout. More sophisticated idle processing schemes can be achieved using processEvents().


Цитата

bool QEventLoop::processEvents ( ProcessEventsFlags  flags = AllEvents )

Processes pending events that match flags until there are no more events to process.

This function is especially useful if you have a long running operation and want to show its progress without allowing user input; i.e. by using the ExcludeUserInputEvents flag.

This function is simply a wrapper for QAbstractEventDispatcher::processEvents(). See the documentation for that function for details.

не лучше ли этим?
Код

qApp->processEvents()


Добавлено через 1 минуту и 40 секунд
просто основная идея - оформить получение айпишников простыми функциями типа 
s = getIP(); 
и всё...  smile 

Автор: SABROG 9.6.2010, 13:28
Цитата(CompWorm @  9.6.2010,  12:43 Найти цитируемый пост)
не лучше ли этим?

qApp->processEvents() вернет тебе управление еще до того как в очередь событий поступит сигнал finished(), если только не обернуть его в while.

Цитата(CompWorm @  9.6.2010,  12:43 Найти цитируемый пост)
я так понял, она запускает отдельный поток

Нет, все в том же потоке работает.

Цитата(CompWorm @  9.6.2010,  12:43 Найти цитируемый пост)
крыться опасность? в чём "неправильность?"

Большое количество разнообразных запросов к разным серверам требуют разной реакции, но общей инфраструктуры для их обработки. Если требуется предоставить интерфейс класса для пользователя, то можно и через QEventLoop.

Автор: CompWorm 9.6.2010, 20:54
спасибо +  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)