Thursday, July 14, 2011

Socket - Manipulating IP Numbers

To ease the programming burden of turning IP numbers in string form into usable socket addresses, a number of conversion functions have been provided. These and other useful functions will be presented in the following sections.

Using the inet_addr(3) Function

The first function that you will learn about is an older function, which should probably no longer be
used in new code. However, you will find it in a lot of existing network code, and so you should become familiar with it and know its limitations. The synopsis for inet_addr(3) is as follows:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
unsigned long inet_addr(const char *string);

This function accepts an input C string argument string and parses the dotted-quad notation into a 32-bit Internet address value. The 32-bit value returned is in network byte order. If the input argument string does not represent a valid dotted-quad address, the value INADDR_NONE is returned. Any other returned value represents the converted value.

NOTE
The 32-bit value returned by inet_addr(3) is in network byte order. Do not use htonl(3) on the returned value, because it is already in network byte order.
 
CAUTION
The inet_addr(3) does not establish a reason code in errno when INADDR_NONE is returned. So, do not test errno or report it when an error indication is returned by this function.

The program shown below is an example of how you would use this function. To compile and run the program, perform the following:
 
c++ -c -D_GNU_SOURCE -Wall inetaddr.cpp
c++ inetaddr.o -o inetaddr
./inetaddr

The program, when it is run, converts a C string constant containing an IP number into a network sequenced 32-bit IP address. This value is then placed into an AF_INET socket address and bound to the socket.

/*
 * inetaddr.cpp
 * using inet_addr function call tp take IP address.
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>

using namespace std;

static void sockError(const char *on_what)
{
    fputs(on_what,stderr);
    fputc('/n',stderr);
    exit(1);
}
int main(int argc,char **argv)
{
    int z;
    struct sockaddr_in adr_inet;     // AF_INET
    int len_inet;                    // length
    int sck_inet;                    // Socket
/*
 * Create a Socket
 */
    sck_inet = socket(AF_INET,SOCK_STREAM,0);
  
    if ( sck_inet == -1 ) {
        sockError("socket()");
    }
    memset(&adr_inet,0,sizeof adr_inet);
    adr_inet.sin_family = AF_INET;
    adr_inet.sin_port = htons(9000);
    adr_inet.sin_addr.s_addr = inet_addr("192.168.22.55");
    if ( adr_inet.sin_addr.s_addr == INADDR_NONE ) {
        sockError("bad address.");
    }
    len_inet = sizeof adr_inet;
/*
 * Bind it to the socket
 */
    z = bind(sck_inet,(struct sockaddr *)&adr_inet,len_inet);
    if ( z == -1 ) {
        sockError("bind()");
    }
/*
 * Display our socket address
 */
    system("netstat -pa --tcp 2>/dev/null | grep inetaddr");
    return 0;
}

--------------------------------------------------------

The inet_aton(3) Function

The inet_aton(3) is an improved way to convert a string IP number into a 32-bit networked sequenced IP number. The synopsis of the function is given as follows:

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

int inet_aton(const char *string, struct in_addr *addr);

The inet_aton(3) function accepts two arguments. They are
1. The input argument string, which contains the ASCII representation of the dotted-quad IP number.
2. The output argument addr is the structure that will be updated with the new IP address.

The return value of the function is nonzero (true) if the conversion succeeds. The value zero (false) is returned if the input address is incorrect. There is no error code established in errno, so its value should be ignored.
What is a little bit confusing about this function is the pointer required for argument two of this function call. If you define an AF_INET socket address as

struct sockaddr_in adr_inet; /* AF_INET */

the pointer that should be supplied as argument two of the inet_aton(3) function is the following:

&adr_inet.sin_addr

Program shows a program that calls upon inet_aton(3) instead of the older inet_addr(3) function that you learned about in the previous section. This program operates the same way, except
that it is compiled and executed as follows:

c++ -c -D_GNU_SOURCE -Wall inetaton.cpp
c++ inetaton.o -o inetaton
./inetaton


/**************
* Program Name  : inetaton.cpp
* Discription   : using inet_aton to assign address to the socket
****************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>

int main()
{
     int n_sock;
     n_sock = socket (AF_INET, SOCK_STREAM, 0);
    
     if (n_sock == FAILURE){
           cout << "socket creation failed! ERROR : " << strerror(errno) << endl;
     }
     struct sockaddr_in adr_inet;
     int len_inet;
     int sock_inet;
    
     memset(&adr_inet, 0, sizeof adr_inet);
    
     adr_inet.sin_family = AF_INET;
     adr_inet.sin_port   = htons (9000);
    
     if ( !inet_aton("192.168.22.55", &adr_inet.sin_addr) ){
           cout << "inet_ntoa failed" << endl;
     }
     cout << "IP address is :: " << inet_ntoa(adr_inet.sin_addr) << endl;
    
     int z = bind (n_sock, (struct sockaddr*) &adr_inet, sizeof adr_inet);
    
     if (z == FAILURE) {
           cout << "bind() failed" << endl;
     }
     return 0;
}

-----------------------------------------------

No comments:

Post a Comment