Вот собственно такая задача... Нужно получить собственный IP-адрес и отправить его на сервер, чтобы сервер переслал его другому клиенту. Что бы тот к нам присоединился... Ну это собственно частности, но главный вопрос - как получить собственный IP, есть какаие-нибудь системные вызовы или только ручками в конфигурации прописывать?
> Вот собственно такая задача... Нужно получить собственный IP-адрес и отправить
>его на сервер, чтобы сервер переслал его другому клиенту. Что бы
>тот к нам присоединился... Ну это собственно частности, но главный вопрос
>- как получить собственный IP, есть какаие-нибудь системные вызовы или только
>ручками в конфигурации прописывать?
У провайдера своего получить!!!!
>- как получить собственный IP, есть какаие-нибудь системные вызовы или только
>ручками в конфигурации прописывать?ip адрес это не свойство сервера, это свойство интерфейса. И ip адресов может быть много на сервере. Вот пример:
# ifconfig |grep -c inet
53Какой из них ты хочешь получить?
P.S. хоть бы язык программирования указал :)
>>- как получить собственный IP, есть какаие-нибудь системные вызовы или только
>>ручками в конфигурации прописывать?
>
>ip адрес это не свойство сервера, это свойство интерфейса. И ip адресов
>может быть много на сервере. Вот пример:
>
># ifconfig |grep -c inet
>53
>
>Какой из них ты хочешь получить?
>
>P.S. хоть бы язык программирования указал :)
Язык Cи, мм, вот и я думаю... Какой хочу? Походу я даже и не могу знать, какой надо получать... Это наверно только пользователю программы должно быть известно, какой IP отправлять, т.е. по-сути в какой подсети будет работать эта прога (конечно если нат нет)... Т.е. только указание вручную. :-( Ну ладно, пусть пользователи заморачиваются с ещё одной настройкой... :-)
>и не могу знать, какой надо получать... Это наверно только пользователю
>программы должно быть известно, какой IP отправлять, т.е. по-сути в какой
>подсети будет работать эта прога (конечно если нат нет)... Т.е. толькоТы не понял.
У хоста может быть куча интерфейсов. Часть из них физические, с каждым из них может быть связано несколько логических. У любого интерфейса может быть свой адрес. То есть у одного хоста может быть, например, 50000 IP адресов.
Далее, адрес, с которого серверу приходят пакеты, может быть адресом firewall, например. Что толку прислать серверу свой адрес 192.168.10.10, если он существует только внутри твоей сети?
1. Почитай теорию IP + маршрутизацию + firewalls/nat/proxy/etc.
2. Думай над постановкой задачи - задача поставлена неправильно.
>Ты не понял.
>
>У хоста может быть куча интерфейсов. Часть из них физические, с каждым
>из них может быть связано несколько логических. У любого интерфейса может
>быть свой адрес. То есть у одного хоста может быть, например,
>50000 IP адресов.
>
>Далее, адрес, с которого серверу приходят пакеты, может быть адресом firewall, например.
>Что толку прислать серверу свой адрес 192.168.10.10, если он существует только
>внутри твоей сети?
>
>1. Почитай теорию IP + маршрутизацию + firewalls/nat/proxy/etc.
>2. Думай над постановкой задачи - задача поставлена неправильно.Вот про что я и говорю, что смысла в получении нет, т.к. может быть куча интерфейсов в том числе несвязвнных друг с другом (нат). И потому автоматически сообразить, какой слать невозможно, т.к. можно послать адрес с другого интерфейса, который не будет доступен тому пользователю, которому предназначается этот адрес.
В общем-то на первый поставленный вопрос ответ я получил, пасибо.А насчёт "ты не понял", это просто я не польностью сформулировал задачу. А задача была такая - есть сервер, у него куча клиентов. Обмен сообщ. клиентов идёт через сервер. Но иногда, для отсылки большого объёма данных, клиент может сам запустить у себя сервер, и отправить через главный сервер информационный пакет с адресом и портом своего личного сервера другому клиенту, чтобы тот присоединился к нему напрямую, минуя главный сервер. Вот для этого и нужно определить свой адрес, т.к. клиенты не знают адреса друг друга.
Ну я уже понял, что это возможно только вручную и осмысленно. Т.е. повторюсь, ответ я получил - спасибо.
>Вот про что я и говорю, что смысла в получении нет, т.к.
>может быть куча интерфейсов в том числе несвязвнных друг с другом
>(нат). И потому автоматически сообразить, какой слать невозможно, т.к. можно послать
>адрес с другого интерфейса, который не будет доступен тому пользователю,
>которому предназначается этот адрес.Не совсем согласен с утверждением о бессмысленности получения адресов.
Во первых, если получить адреса и выдать их пользователю, то ему будет легче сориентироваться, какой адрес использовать
Во вторых, можно дать программе знания о том, какие адреса обычно используются для каких целей - например если прога найдет на своих интерфейсах адрес 192.168.х.х, то она вполне может сообразить, что это адрес из локалки. Т.е. можно все-таки снять с юзверя часть забот, так как обычно у компа не 50000 адресов, а тока 1 - 2.
>А задача была такая - есть сервер, у
>него куча клиентов. Обмен сообщ. клиентов идёт через сервер. Но иногда,
>для отсылки большого объёма данных, клиент может сам запустить у себя
>сервер, и отправить через главный сервер информационный пакет с адресом и
>портом своего личного сервера другому клиенту, чтобы тот присоединился к нему
>напрямую, минуя главный сервер. Вот для этого и нужно определить свой
>адрес, т.к. клиенты не знают адреса друг друга.Как уже упоминалось сервер и так знает адрес клиента при подключении: он его получается по accept или в любой момент может узнать используя getpeername . Соответственно единственное, что осталось сделать, это попробовать серверу попытаться присоединиться к клиенту на определенный порт (жестко заданый в протоколе или переданый клиентом серверу) и в зависимости от удачности или неудачности попытки сделать выводы о возможности или невозможности общения с этим клиентом напрямую.
Когда клиент коннектится к серверу, сервер уже получает ИП клиента
для tcp:
accept(sock,(struct sockaddr *)&accept_sin,&accept_sin_len);
printf("Client ip: %s", inet_ntoa(accept_sin.sin_addr));для UDP смотри man recvfrom
accept() mozhet i ne srabotat' - esli, k primeru, konekt proksiruetsya na kakom-nibud' promezhutochnom gateway.Mozhno sdelat' tak - posle ustanovleniya soedineniya s erverom sdelat' getsockname() - i poluchenyi adres otpravit'.
> Вот собственно такая задача... Нужно получить собственный IP-адрес и отправитьКак уже упоминалось IP является свойством интерфейса (причем существует еще такое понятие как алиасы). Так вот получить адресы и алиасы интерфейсов можно с помощью man 3 getifaddrs
> Вот собственно такая задача... Нужно получить собственный IP-адрес и отправить
>его на сервер, чтобы сервер переслал его другому клиенту. Что бы
>тот к нам присоединился... Ну это собственно частности, но главный вопрос
>- как получить собственный IP, есть какаие-нибудь системные вызовы или только
>ручками в конфигурации прописывать?Через ioctl'ы параметры сетевых интерфейсов вытаскиваются вот так:
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netdb.h>
#include <stdio.h>#define MAX_NUM_IFREQ 512
int main(int argc, char ** argv)
{
struct ifconf Ifc;
struct ifreq IfcBuf[MAX_NUM_IFREQ], *pIfr;
int num_ifreq, i, fd;
struct sockaddr_in addrtmp;
unsigned char mac[10]={0};Ifc.ifc_len=sizeof(IfcBuf);
Ifc.ifc_buf=(char *)IfcBuf;if ((fd=socket(AF_INET, SOCK_DGRAM, 0))<0) { perror("ERROR socket(): "); return 1; }
if (ioctl(fd, SIOCGIFCONF, &Ifc)<0) { perror("ERROR ioctl(SIOCGIFCONF): "); close(fd); return 1; }
num_ifreq=Ifc.ifc_len/sizeof(struct ifreq);for (pIfr=Ifc.ifc_req, i=0; i<num_ifreq; ++pIfr, ++i)
{
if (pIfr->ifr_addr.sa_family!=AF_INET) continue; // I dont need not internet interfaces
printf("\n[%d] Name = %s\n", i, pIfr->ifr_name);
if (ioctl(fd,SIOCGIFHWADDR, pIfr)<0) { perror("ERROR ioctl(SIOCGIFHWADDR): "); continue; }
memcpy(mac,(unsigned char *)&(pIfr->ifr_hwaddr.sa_data),sizeof(struct sockaddr));
printf("[%d] MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
if (ioctl(fd, SIOCGIFADDR, pIfr)<0) { perror("ERROR ioctl(SIOCGIFADDR): "); continue; }
memcpy(&addrtmp,&(pIfr->ifr_addr),sizeof(addrtmp));
printf("[%d] Address = %s\n",i, inet_ntoa(addrtmp.sin_addr));
if (ioctl(fd, SIOCGIFBRDADDR, pIfr)<0) { perror("ERROR ioctl(SIOCGIFBRDADDR): "); continue; }
memcpy(&addrtmp,&(pIfr->ifr_broadaddr),sizeof(addrtmp));
printf("[%d] BroadAddress = %s\n",i, inet_ntoa(addrtmp.sin_addr));
if (ioctl(fd, SIOCGIFNETMASK, pIfr)<0) { perror("ERROR ioctl(SIOCGIFNETMASK): "); continue; }
memcpy(&addrtmp,&(pIfr->ifr_addr),sizeof(addrtmp));
printf("[%d] MaskAddress = %s\n",i, inet_ntoa(addrtmp.sin_addr));
if (ioctl(fd, SIOCGIFFLAGS, pIfr)<0) { perror("ERROR ioctl(SIOCGIFFLAGS): "); continue; }
printf("[%d] IFF_UP=%s\n",i, pIfr->ifr_flags&0x1?"ON":"OFF");
printf("[%d] IFF_BROADCAST=%s\n",i, pIfr->ifr_flags&0x2?"ON":"OFF");
printf("[%d] IFF_DEBUG=%s\n",i, pIfr->ifr_flags&0x4?"ON":"OFF");
printf("[%d] IFF_LOOPBACK=%s\n",i, pIfr->ifr_flags&0x8?"ON":"OFF");
printf("[%d] IFF_P2P=%s\n",i, pIfr->ifr_flags&0x10?"ON":"OFF");
printf("[%d] IFF_NOTRAILERS=%s\n",i, pIfr->ifr_flags&0x20?"ON":"OFF");
printf("[%d] IFF_RUNNING=%s\n",i, pIfr->ifr_flags&0x40?"ON":"OFF");
printf("[%d] IFF_NOARP=%s\n",i, pIfr->ifr_flags&0x80?"ON":"OFF");
}
close(fd);
return 0;
}С помощью обвязки getifaddrs вот так (только мак-адресом придется пожертвовать):
#include <ifaddrs.h>
#include <netinet/in.h>
#include <stdio.h>int main(int argc, char ** argv)
{
struct ifaddrs *ifa_ptr, *ifa_ptr_tmp;if (getifaddrs(&ifa_ptr)!=0) { perror("ERROR getifaddrs: "); return 1;}
for (ifa_ptr_tmp=ifa_ptr; ifa_ptr_tmp->ifa_next!=NULL; ifa_ptr_tmp=ifa_ptr_tmp->ifa_next)
{
if (ifa_ptr_tmp->ifa_addr->sa_family!=AF_INET) continue; // I dont need not internet interfaces
printf("\nName = %s\n", ifa_ptr_tmp->ifa_name);
printf("Address = %s\n", inet_ntoa(((struct sockaddr_in *)(ifa_ptr_tmp->ifa_addr))->sin_addr));
printf("BroadAddress = %s\n", inet_ntoa(((struct sockaddr_in *)(ifa_ptr_tmp->ifa_broadaddr))->sin_addr));
printf("MaskAddress = %s\n", inet_ntoa(((struct sockaddr_in *)(ifa_ptr_tmp->ifa_netmask))->sin_addr));
printf("IFF_UP=%s\n", ifa_ptr_tmp->ifa_flags&0x1?"ON":"OFF");
printf("IFF_BROADCAST=%s\n", ifa_ptr_tmp->ifa_flags&0x2?"ON":"OFF");
printf("IFF_DEBUG=%s\n", ifa_ptr_tmp->ifa_flags&0x4?"ON":"OFF");
printf("IFF_LOOPBACK=%s\n", ifa_ptr_tmp->ifa_flags&0x8?"ON":"OFF");
printf("IFF_P2P=%s\n", ifa_ptr_tmp->ifa_flags&0x10?"ON":"OFF");
printf("IFF_NOTRAILERS=%s\n", ifa_ptr_tmp->ifa_flags&0x20?"ON":"OFF");
printf("IFF_RUNNING=%s\n", ifa_ptr_tmp->ifa_flags&0x40?"ON":"OFF");
printf("IFF_NOARP=%s\n", ifa_ptr_tmp->ifa_flags&0x80?"ON":"OFF");
}
freeifaddrs(ifa_ptr);
return 0;
}
Ну во-первых нужно знать исходящий интерфейс и сетку.
Это только после роутинга можно сделать. Поэтому решение такое:1. Проверка таблицы маршрутизации.
Можно типа так, если самому влом:root@debian:~# ip route get 213.180.204.8
213.180.204.8 via 10.0.0.1 dev eth0 src 10.0.0.25
cache mtu 1500 advmss 1460 hoplimit 64
root@debian:~#Исходя из этого, в сторону яндекса у меня смотрит eth0 и исход будет
с ip 10.0.0.25.Выполнить это с помощью popen, к примеру.
2. Пропарсить результат на предмет SRC ip...
> Вот собственно такая задача... Нужно получить собственный IP-адрес и отправить
>его на сервер, чтобы сервер переслал его другому клиенту. Что бы
>тот к нам присоединился... Ну это собственно частности, но главный вопрос
>- как получить собственный IP, есть какаие-нибудь системные вызовы или только
>ручками в конфигурации прописывать?