На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > Поиск доступных сетевых интерфейсов по ip 4 и ip 6 , Получение всех ip 4 и ip 6 адресов компьютера
      Откопал в сети функции поиска доступных интерфейсов по ip 4 и ip 6 (для ip 6 переделал из ip 4 сам):

      ExpandedWrap disabled
        const int BUF_SIZE = 4092;
         
        int lookup_addr_indx_ip_4(int indx,
                                  unsigned long *addr)
        {
        #ifdef WIN32
            LPSOCKET_ADDRESS_LIST list = NULL;
            SOCKET  sc = 0;
            char  buf[BUF_SIZE];
            int len = 0;
            int ret = 0;
         
            sc = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
            if(sc == INVALID_SOCKET){
                return (-1);
            }
            ret = WSAIoctl(sc,
                SIO_ADDRESS_LIST_QUERY,
                NULL,
                0,
                buf,
                BUF_SIZE,
                (unsigned long *)&len,
                NULL,
                NULL);
            closesocket(sc);
            if(ret != 0 || len <= 0){
                return(-2);
            }
            list = (LPSOCKET_ADDRESS_LIST) buf;
            if(list->iAddressCount <=0){
                return (-3);
            }
            for(int i = 0; i <= indx && i < list->iAddressCount; ++i){
                //нашли адрес
                if(i == indx){
                    memcpy(addr,
                        &list->Address[i].lpSockaddr->sa_data[2],4);
                    return (1);
                }
            }
            //адресов не осталось
            return (0);
        #else
            struct ifconf ifc;
            struct ifreq *ifr = NULL;
            char buf[BUF_SIZE];
            int ret = 0;
            int off = 0;
            int cnt = 0;
            int cdx = 0;
            int sc = 0;
            sc = socket(AF_INET, SOCK_DGRAM, 0);
            if(sc < 0){
                return (-1);
            }
            ifc.ifc_len = BUF_SIZE;
            ifc.ifc_buf = buf;
            ret = ioctl(sc, SIOCGIFCONF, &ifc);
            if(ret <0){
                return (-2);
            }
            ifr = ifc.ifc_req;
            while(cnt < ifc.ifc_len && cdx <= indx){
                if(ifr->ifr_addr.sa_family == AF_INET){
                    if(cdx == indx){
                        memcpy(addr, &ifr->ifr_addr.sa_data[2], 4);
                        return (1);
                    }
                    ++cdx;
                }
                off = IFNAMSIZ + ifr->ifr_addr.sa_len;
                cnt += off;
                ((char*) ifr) += off;
            }
            close(sc);
        #endif
            return (0);
        }


      ExpandedWrap disabled
        const int BUF_SIZE = 4092;
         
        int lookup_addr_indx_ip_6(int indx,
                                  sockaddr_in6 *addr)
        {
        #ifdef WIN32
            LPSOCKET_ADDRESS_LIST list = NULL;
            SOCKET  sc = 0;
            char  buf[BUF_SIZE];
            int len = 0;
            int ret = 0;
         
            sc = socket(AF_INET6, SOCK_RAW, IPPROTO_IP);
            if(sc == INVALID_SOCKET){
                return (-1);
            }
            ret = WSAIoctl(sc,
                SIO_ADDRESS_LIST_QUERY,
                NULL,
                0,
                buf,
                BUF_SIZE,
                (unsigned long *)&len,
                NULL,
                NULL);
            closesocket(sc);
            if(ret != 0 || len <= 0){
                return(-2);
            }
            list = (LPSOCKET_ADDRESS_LIST) buf;
            if(list->iAddressCount <=0){
                return (-3);
            }
            for(int i = 0; i <= indx && i < list->iAddressCount; ++i){
                //нашли адрес
                if(i == indx){
                    memcpy(addr,
                        list->Address[i].lpSockaddr,list->Address[i].iSockaddrLength);
                    return (1);[attach=48013][/attach][attach=48013][/attach]
                }
            }
            //адресов не осталось
            return (0);
        #else
            struct ifconf ifc;
            struct ifreq *ifr = NULL;
            char buf[BUF_SIZE];
            int ret = 0;
            int off = 0;
            int cnt = 0;
            int cdx = 0;
            int sc = 0;
            sc = socket(AF_INET6, SOCK_DGRAM, 0);
            if(sc < 0){
                return (-1);
            }
            ifc.ifc_len = BUF_SIZE;
            ifc.ifc_buf = buf;
            ret = ioctl(sc, SIOCGIFCONF, &ifc);
            if(ret <0){
                return (-2);
            }
            ifr = ifc.ifc_req;
            while(cnt < ifc.ifc_len && cdx <= indx){
                if(ifr->ifr_addr.sa_family == AF_INET){
                    if(cdx == indx){
                        memcpy(addr, &ifr->ifr_addr.sa_data[2], 4);
                        return (1);
                    }
                    ++cdx;
                }
                off = IFNAMSIZ + ifr->ifr_addr.sa_len;
                cnt += off;
                ((char*) ifr) += off;
            }
            close(sc);
        #endif
            return (0);
        }


      Для ip 6 находит 7 адресов на моём компьютера, но некоторые отличаются с "Сведения" Windows.
      Неплохо бы это ещё исправить.

      Прикреплённая картинка
      Прикреплённая картинка


      Теперь из-за использования сырых сокетов (SOCK_RAW) программа в Windows 10 требует административных прав.

      Прошу предложить мне готовые функции для нахождения всех ip 4 и ip 6 адресов компьютера без использования сырых сокетов (SOCK_RAW).
      Сообщение отредактировано: Kozlov_Sergey -
        Вот для ipv4:

        ExpandedWrap disabled
          CStringA local_address;
           
                              CStringA local_address_internet_address;
           
           
                              char chInfo[64];
                              if (!gethostname(chInfo,sizeof(chInfo)))
                              {
                                  hostent *sh;
                                  sh=gethostbyname((char*)&chInfo);
                                  if (sh!=NULL)
                                  {
                                      int nAdapter = 0;
                                      while ( sh->h_addr_list[nAdapter] )
                                      {
                                          struct sockaddr_in adr;
                                          memcpy(&adr.sin_addr,sh->h_addr_list[nAdapter],sh->h_length);
                                          local_address += CStringA(inet_ntoa(adr.sin_addr)) + CStringA("\n");
                                          nAdapter++;
                                      }
                                  }
                              }
           
                              if(local_address.GetLength()==0)
                              {
                                  CString error(L"local_address.GetLength()==0");
                                  ::MessageBox(0,error,CString(L"Error"),MB_ICONERROR);
           
                                  break;
                              }
           
                              //::MessageBox(0,CString(local_address),CString(L"Information"),MB_ICONINFORMATION);
           
                              CStringA local_first_address;
           
                              int pos_return = local_address.Find('\n');
           
                              if(pos_return!=0)
                              {
                                  for(int local_counter=0;local_counter<pos_return;local_counter++)
                                  {
                                      local_first_address += local_address.GetAt(local_counter);
                                  }
                                  local_address = local_first_address;
                              }


        Теперь надо сделать для ipv6.

        Добавлено
        Вот программа с сайта microsoft (я немного переделал):

        ExpandedWrap disabled
          #include <winsock2.h>
          #include <ws2tcpip.h>
          #include <stdio.h>
           
          // link with Ws2_32.lib
          #pragma comment (lib, "Ws2_32.lib")
           
          int __cdecl main(int argc, char **argv)
          {
           
              //-----------------------------------------
              // Declare and initialize variables
              WSADATA wsaData;
              int iResult;
              INT iRetval;
           
              DWORD dwRetval;
           
              int i = 1;
              
              struct addrinfo *result = NULL;
              struct addrinfo *ptr = NULL;
              struct addrinfo hints;
           
              struct sockaddr_in  *sockaddr_ipv4;
          //    struct sockaddr_in6 *sockaddr_ipv6;
              LPSOCKADDR sockaddr_ip;
           
              wchar_t ipstringbuffer[46];
              DWORD ipbufferlength = 46;
           
              // Validate the parameters
              if (argc != 3) {
                  printf("usage: %s <hostname> <servicename>\n", argv[0]);
                  printf("getaddrinfo provides protocol-independent translation\n");
                  printf("   from an ANSI host name to an IP address\n");
                  printf("%s example usage\n", argv[0]);
                  printf("   %s www.contoso.com 0\n", argv[0]);
                  return 1;
              }
           
              // Initialize Winsock
              iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
              if (iResult != 0) {
                  printf("WSAStartup failed: %d\n", iResult);
                  return 1;
              }
           
              //--------------------------------
              // Setup the hints address info structure
              // which is passed to the getaddrinfo() function
              ZeroMemory( &hints, sizeof(hints) );
              hints.ai_family = AF_UNSPEC;
              hints.ai_socktype = SOCK_STREAM;
              hints.ai_protocol = IPPROTO_TCP;
           
              printf("Calling getaddrinfo with following parameters:\n");
              printf("\tnodename = %s\n", argv[1]);
              printf("\tservname (or port) = %s\n\n", argv[2]);
              
          //--------------------------------
          // Call getaddrinfo(). If the call succeeds,
          // the result variable will hold a linked list
          // of addrinfo structures containing response
          // information
              dwRetval = getaddrinfo(argv[1], argv[2], &hints, &result);
              if ( dwRetval != 0 ) {
                  printf("getaddrinfo failed with error: %d\n", dwRetval);
                  WSACleanup();
                  return 1;
              }
           
              printf("getaddrinfo returned success\n");
              
              // Retrieve each address and print out the hex bytes
              for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
           
                  printf("getaddrinfo response %d\n", i++);
                  printf("\tFlags: 0x%x\n", ptr->ai_flags);
                  printf("\tFamily: ");
                  switch (ptr->ai_family) {
                      case AF_UNSPEC:
                          printf("Unspecified\n");
                          break;
                      case AF_INET:
                          printf("AF_INET (IPv4)\n");
                          sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
                          printf("\tIPv4 address %s\n",
                              inet_ntoa(sockaddr_ipv4->sin_addr) );
                          break;
                      case AF_INET6:
                          printf("AF_INET6 (IPv6)\n");
                          // the InetNtop function is available on Windows Vista and later
                          // sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
                          // printf("\tIPv6 address %s\n",
                          //    InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstringbuffer, 46) );
                          
                          // We use WSAAddressToString since it is supported on Windows XP and later
                          sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
                          // The buffer length is changed by each call to WSAAddresstoString
                          // So we need to set it for each iteration through the loop for safety
                          ipbufferlength = 46;
                          iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL,
                              ipstringbuffer, &ipbufferlength );
                          if (iRetval)
                              printf("WSAAddressToString failed with %u\n", WSAGetLastError() );
                          else    
                              wprintf(L"\tIPv6 address %s\n", ipstringbuffer);
                          break;
                      case AF_NETBIOS:
                          printf("AF_NETBIOS (NetBIOS)\n");
                          break;
                      default:
                          printf("Other %ld\n", ptr->ai_family);
                          break;
                  }
                  printf("\tSocket type: ");
                  switch (ptr->ai_socktype) {
                      case 0:
                          printf("Unspecified\n");
                          break;
                      case SOCK_STREAM:
                          printf("SOCK_STREAM (stream)\n");
                          break;
                      case SOCK_DGRAM:
                          printf("SOCK_DGRAM (datagram) \n");
                          break;
                      case SOCK_RAW:
                          printf("SOCK_RAW (raw) \n");
                          break;
                      case SOCK_RDM:
                          printf("SOCK_RDM (reliable message datagram)\n");
                          break;
                      case SOCK_SEQPACKET:
                          printf("SOCK_SEQPACKET (pseudo-stream packet)\n");
                          break;
                      default:
                          printf("Other %ld\n", ptr->ai_socktype);
                          break;
                  }
                  printf("\tProtocol: ");
                  switch (ptr->ai_protocol) {
                      case 0:
                          printf("Unspecified\n");
                          break;
                      case IPPROTO_TCP:
                          printf("IPPROTO_TCP (TCP)\n");
                          break;
                      case IPPROTO_UDP:
                          printf("IPPROTO_UDP (UDP) \n");
                          break;
                      default:
                          printf("Other %ld\n", ptr->ai_protocol);
                          break;
                  }
                  printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
                  printf("\tCanonical name: %s\n", ptr->ai_canonname);
              }
           
              freeaddrinfo(result);
              WSACleanup();
           
              return 0;
          }


        Прошу переделать в функцию.
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0645 ]   [ 17 queries used ]   [ Generated: 6.05.24, 14:09 GMT ]