Sockets


Match word(s).

If you have any questions or comments,
please visit us on the Forums.

FAQ > Linux/Unix Specific > Sockets

This item was added on: 2003/03/07

  • How do I get my own IP address?

  • How do I convert an IP address to a hostname and vice-versa?

  • How do I test for input on a socket, before performing a read()/recv()?

  • Nonblocking descriptors and polling are fine, but I really need more than one thread of execution. What can I do?


  • How do I get my own IP address?

    By far the easiest and most portable way is to apply getsockname() to a connected socket.

    
    socklen_t len;
    struct sockaddr_in  other, me;
    
    /* ... */
    len = sizeof(me);
    if (connect(some_socket, (struct sockaddr *) &other, sizeof(other)) == 0)
    {
      if (getsockname(some_socket, (struct sockaddr *) &me, &len) != 0)
      {
        /* getsockname( ) error */
      }
    }
    
    



    How do I convert an IP address to a hostname and vice-versa?

    For IPv4:

    
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <netdb.h> 
    
    struct hostent  *h;
    char            *addr = "127.0.0.1";
    int             a = inet_addr(addr);
    h = gethostbyaddr((const char *) &a, sizeof(a), AF_INET);
    if (h)
    {
      printf("%s\n", h->h_name);
    }
    else
    {
      /* gethostbyaddr( ) error */
    }
    
    

    
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <netdb.h> 
    
    struct hostent  *h;
    char            *host = "localhost";
    h = gethostbyname(host);
    if (h)
    {
      printf("%s\n", inet_ntoa(*(struct in_addr *) h->h_addr_list[0]));
    }
    else
    {
      /* gethostbyname( ) error */
    }
    
    

    For IPv6:
    
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <netdb.h> 
    
    char            *addr = "3ffe:b00:c18:1::10";
    struct in6_addr i6;
    struct hostent  *h;
    inet_pton(AF_INET6, addr, &i6);
    h = gethostbyaddr((char *) &i, sizeof(i), AF_INET6);
    if (h)
    {
      printf("%s\n", h->h_name);
    }
    
    

    
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/socket.h> 
    #include <netinet/in.h> 
    #include <netdb.h> 
    
    char                *host = "www.6bone.net", buf[INET6_ADDRSTRLEN];
    struct hostent      *h;
    struct sockaddr_in6 s6;
    h = gethostbyname2(host, AF_INET6);
    if (h)
    {
      s6.sin6_addr = *(struct in6_addr *) h->h_addr_list[0];
      inet_ntop(AF_INET6, s6.sin6_addr.s6_addr, buf, sizeof(buf));
      printf("%s\n", buf);
    }
    



    How do I test for input on a socket, before performing a read()/recv()?

    Option 1: Make the descriptor non-blocking:

    
    #include <fcntl.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <stdio.h> 
    
    int   rc;
    char  buf[128];
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
    errno = 0;
    rc = read(STDIN_FILENO, buf, 127);
    if (rc == -1)
    {
      if (errno == EAGAIN)
      {
        /* no input available */
      }
      else
      {
        /* read( ) error */
      }
    }
    buf[rc] = 0;
    printf("%s", buf);
    
    

    Option 2: Use select() or poll().

    
    #include <sys/types.h> 
    #include <sys/time.h> 
    #include <unistd.h> 
    #include <stdio.h> 
    
    fd_set          f;
    int             rc;
    char            buf[128];
    struct timeval  t;
    
    /* no delay */
    t.tv_sec = 0;
    t.tv_usec = 0;
    
    /* set descriptor */
    FD_ZERO(&f);
    FD_SET(STDIN_FILENO, &f);
    
    rc = select(STDIN_FILENO + 1, &f, NULL, NULL, &t);
    if (rc == -1)
    {
      /* select( ) error */
    }
    else if (rc == 0)
    {
      /* no input available */
    }
    else if (FD_ISSET(STDIN_FILENO, &f))
    {
      rc = read(STDIN_FILENO, buf, 127);
      if (rc == -1)
      {
        /* read( ) error */
      }
      else
      {
        buf[rc] = 0;
        printf("%s", buf);
      }
    }
    
    

    You can test more than one descriptor, which makes this solution interesting for servers that have to handle multiple clients synchronously. It could be used like:

    
    int largest = 0;
    FD_ZERO(&f);
    for (i = 0; i < number_of_sockets; ++i)
    {
      FD_SET(sockets[i], &f);
      if (largest < sockets[i])
      {
        largest = sockets[i];
      }
    }
    rc = select(largest + 1, &f, NULL, NULL, &t);
    if (rc == -1)
    {
      /* select( ) error */
    }
    else if (rc == 0)
    {
      /* no socket ready */
    }
    else
    {
      for (i = 0; i < number_of_sockets; ++i)
      {
        if (FD_ISSET(sockets[i], &f))
        {
          /* input available */
        }
      }
    }
    
    



    Nonblocking descriptors and polling are fine, but I really need more than one thread of execution. What can I do?

    Use either multiple processes or POSIX threads. There are few situations where processes are to be preferred over threads, the most obvious one is if you want to exec*() another program. Most fork() implementations use a copy-on-write technique that has child and parent share all physical memory pages until one of them attempts to modify a page, in which case it gets a copy of it. This is still less efficient than always using the same virtual and physical pages. Also, if processes want to communicate with each other, they need some form of IPC, like sockets, (named) pipes, record locking, message queues, shared memory, semaphores. POSIX threads share the same address space, so shared data access is less of a problem - Only mutexes are needed to avoid race conditions and to guarantee proper memory visibility on certain symmetric multiprocessor machines.

    Here's how you create a new process:

    
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <stdio.h> 
    
    pid_t child;
    child = fork();
    if (child == -1)
    {
      /* fork( ) error */
    }
    else if (child == 0)
    {
      puts("Hi, I am the new (child) process");
      _exit(0);                 /* exit child */
    }
    else
    {
      printf("Hi, I am the parent. My child's PID is: %u\n", child);
      waitpid(child, NULL, 0);  /* wait for child to exit */
    }
    
    

    Here's how you create a new thread:

    
    #include <pthread.h> 
    
    void *threadfunc(void *arg)
    {
      puts("Hi, I'm the new thread");
      return(NULL);
    }
    
    pthread_t p;
    int       data = 123, rc;
    rc = pthread_create(&p, NULL, threadfunc, &data);
    if (rc != 0)
    {
      fprintf(stderr, "pthread_create: %s\n", strerror(rc));
    }
    else
    {
      /* thread running */
    }
    
    

    Note that all threads will exit when the initial thread (main()) exits, so you either have to wait for them to complete, or exit using pthread_exit();

    
    if( pthread_create( &p, ... ) ) 
    {
      pthread_join( p, NULL );
    }
    
    /* ... */
    
    int rc = 0;
    pthread_exit( &rc );
    
    

    Compile with the -pthread or -lpthread flag if you're using POSIX threads.


    Credit: vVv

    Script provided by SmartCGIs