Sunday, August 7, 2011

Obtaining a Peer Socket Address


In the last section, you saw that the function getsockname(2) is quite useful at obtaining a socket's address. However, there will be times when your code will want to determine the remote address that your socket is connected to. Determining the remote address of a socket is like finding out the caller's telephone number when they have called you— similar to North America's CallerID. The function to do this is called getpeername(2). This function will be useful to you when you start examining and writing server code. It is introduced here because it is so similar to getsockname(2). The function synopsis for getpeername(2) is as follows:

#include <sys/socket.h>
int getpeername(int s, struct sockaddr *name, socklen_t *namelen);

You can see that the function arguments are identical to the getsockname(2) function. For completeness, the arguments are described again as follows:

Listing below shows some code that defines a function named peer_addr(). This code is very similar in design to the sock_addr() function of Listing below This is not a complete example, however, because it shows the source code only for the function itself (it lacks a main program). This code can be revisited later in this book, when connection-oriented communications are discussed. For now, simply appreciate it as an example of how the function getpeername(2) can be used.
  1. The socket s to query for the socket address.
  2. The pointer to the receiving buffer (argument name).
  3. Pointer to the maximum length variable. This variable provides the maximum length in bytes that can be received in the buffer (argument namelen). This value is updated with the actual number of bytes written to the receiving buffer.

The function returns zero if the operation succeeds. If an error occurs, the value -1 is returned and the value errno will contain the reason for the error.

/* getpeer.c
 * Demonstrate getpeername(2):
 */
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>


/*
 * This function accepts as input a socket
 * for which a peer socket address must be
 * determined for it. Then the address
 * is converted into a string and returned.
 *
 * If an error occurs, NULL is returned.
 */
 char * peer_addr(int s, char *buf, size_t bufsiz) {
    int z; /* Status return code */
    struct sockaddr_in adr_inet;/* AF_INET */
    int len_inet; /* length */

/*
 * Obtain the address of the socket:
 */
    len_inet = sizeof adr_inet;

    z = getpeername(s, (struct sockaddr *)&adr_inet, &len_inet);
    if ( z == -1) {
       return NULL; /* Failed */
    }

/*
 * Convert address into a string
 * form that can be displayed:
 */
    z = snprintf(buf,bufsiz, "%s:%u",
    inet_ntoa(adr_inet.sin_addr),
   (unsigned)ntohs(adr_inet.sin_port));

    if ( z == -1 ) {
       return NULL; /* Buffer too small */
    }
    return buf;
 }



No comments:

Post a Comment