views:

307

answers:

5

From this code I open a socket (server) and listen for incoming request when someone request accept this and save file descriptor (FD) in newsockfd how to extract IP for requester ?

int sockfd, newsockfd, portno, clilen;
portno = 8090;
clilen = 0;
pthread_t serverIn;
struct sockaddr_in serv_addr, cli_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
    perror("ERROR opening socket");
}
bzero((char *) & serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
serv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *) & serv_addr, sizeof (serv_addr)) < 0)
{
    perror("ERROR on binding");
}

listen(sockfd, 5);
clilen = sizeof (cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) & cli_addr, &clilen);
+4  A: 

getpeername()

See the helpful description of how to use it over at the indispensable Beej's Guide to Network Programming.

Tyler McHenry
No need to call `getpeername()` as `accept()` fills in the client address into its second argument.
Bandi-T
Beej's is a really nice intro.
Flame
(Apologize about mistakenly voting above comment as noise.)
Bandi-T
+2  A: 

You can follow this example :

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>

{
   int s;
   struct sockaddr_in peer;
   int peer_len;
   .
   .
   .
      /* We must put the length in a variable.              */
   peer_len = sizeof(peer);
      /* Ask getpeername to fill in peer's socket address.  */
   if (getpeername(s, &peer, &peer_len) == -1) {
      perror("getpeername() failed");
      return -1;
   }

      /* Print it. The IP address is often zero because     */
      /* sockets are seldom bound to a specific local       */
      /* interface.                                         */
   printf("Peer's IP address is: %s\n", inet_ntoa(peer.sin_addr));
   printf("Peer's port is: %d\n", (int) ntohs(peer.sin_port));
   .
   .
   .
}
SjB
+4  A: 

Your cli_addr already contains the IP address and port of the connected client after accept() returns successfully, in the same format as your serv_addr variable. Use inet_ntop to convert IP to a string.

Nikolai N Fetissov
I need IP for client that connect to me that use getpeername()
Pureth
Hmm, you're confused somewhere. accept() returns client IP and client port in its second argument. You **don't need** to call getpeername(), since that gives you same exact information.
Nikolai N Fetissov
Upvoted. I think the confusion stems from the fact that sockaddr contains the IP as 4 bytes, while the OP needs it in text.
Bandi-T
Completely agree - there's no need to use `getpeername()` in this case, after the `accept()`, `cli_addr.sin_addr` and `cli_addr.sin_port` contain the connecting peer's address and port, in the same format that `getpeername()` returns.
caf
+1  A: 

I think getpeername() is not needed - the client address is already filled into cli_addr by the accept() call.

You only need to use inet_ntop(), getnameinfo(), or gethostbyaddr() to print or get more information.

Bandi-T
A: 

The API is described in the manual pages. You can either browse them from the console, starting with man socket and follow references to man getpeername or use Konqueror, which renders it nicely with links, if you ask for #socket address. In my case on Kubuntu it was necessary to install manpages-dev package.

dhill