Search code examples
c++network-programmingwinsock

How to fetch an IP address of a socket inside a fd_set?


Hey Im storing all connected sockets in a fd_set. I want to iterate through the sockets and display the IP address.

ZeroMemory(host, NI_MAXHOST);
                ZeroMemory(service, NI_MAXSERV);

                inet_ntop(AF_INET, &socketAddr.sin_addr, host, NI_MAXHOST);
                std::cout << host << " connected on port " << ntohs(socketAddr.sin_port) << std::endl;

                if (getnameinfo((sockaddr*)&socketAddr, sizeof(socketAddr), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
                    std::cout << host << " connected on port " << service << std::endl;
                }
                else {
                    inet_ntop(AF_INET, &socketAddr.sin_addr, host, NI_MAXHOST);
                    std::cout << host << " connected on port " << ntohs(socketAddr.sin_port) << std::endl;
                }

I use this way to display the info when a new client joins but this does not seem to work when iterating through sockets already in the fd_set. Im new to socket programming and any help will be greatly appreciated.

Edit: the remote address the socket is connected to


Solution

  • Assuming you are interested in IPv4 and the IP address of the connecting client (as opposed to the server-side IP address), this should work:

    #include <stdio.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    
    // theFDSet is a pointer to your FD_SET object
    // maxFD is the largest file-descriptor value in the set
    void PrintClientAddressesInFDSet(FD_SET * theFDSet, int maxFD)
    {
       for (int i=0; i<=maxFD; i++)
       {
          if (FD_ISSET(i, theFDSet))
          {
             struct sockaddr_in addr;
             socklen_t length = sizeof(sockaddr_in);
             if (getpeername(i, (struct sockaddr *)&addr, &length) == 0)
             {
                printf("Socket FD %i is connected to a peer at IP address %s\n", i, inet_ntoa(addr.sin_addr));
             }
             else perror("getpeername");
          }
       }
    }
    

    For IPv6, you'd need to use inet_ntop() rather than inet_ntoa(), and a sockaddr_in6 rather than a sockaddr.