Administration
  Home arrow Administration arrow Design and Architecture
Dev Shed Forums  
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Smartphone Development  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Mobile Linux  
App Generation ROI  
IBM® developerWorks  
Forums Sitemap  
E-Commerce Hosting  
Linux Web Hosting  
Managed Hosting  
Small Business Hosting  
VPS Hosting  
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid  
Request Media Kit
Contact Us  
Site Map  
Privacy Policy  
Support  
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
ADMINISTRATION

Design and Architecture
By: Apress Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: starstarstarstarstar / 19
    2005-11-03


    Table of Contents:
  • Design and Architecture
  • Multiplexing
  • Forking
  • Preforking: Process Pools
  • Multithreading
  • Combining Preforking and Prethreading
  • Dealing with Large Amounts of Data

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      error-file:tidyout.log Del.ici.ous error-file:tidyout.log Digg
      error-file:tidyout.log Blink error-file:tidyout.log Simpy
      error-file:tidyout.log Google error-file:tidyout.log Spurl
      error-file:tidyout.log Y! MyWeb error-file:tidyout.log Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article

     
     
    ADVERTISEMENT


    Design and Architecture
    ( Page 1 of 7 )

    Servers typically need to be able to handle multiple clients simultaneously. This presents several problems that need to be solved. This article addresses three of those issues: allowing multiple clients to connect and stay connnected, efficient use of resources, and keeping the server responsive to each of the clients. It is excerpted from chapter five of the book The Definitive Guide to Linux Networking Programming, written by Keir Davis et. al. (Apress, 2004; ISBN: 1590593227).

    Client-Server Architecture

    A NETWORK SERVER APPLICATION THAT can handle only one client at a time isn’t very useful. For example, consider an IRC chat application wherein only one client could connect to an IRC chat server at a time. How much fun would it be to chat with yourself? A server is typically required to handle multiple clients simultaneously.

    Handling multiple clients at the same time requires solving several problems. The first issue is allowing multiple clients to connect and stay connected simultaneously. In this chapter, we cover three different general strategies for handling this: multiplexing, forking, and threads. The second issue is one of resources and how to efficiently utilize the memory and processor(s) available. The final issue is keeping the server responsive to each of the clients—in other words, not allowing a client to monopolize the server at the expense of the other connected clients. This is especially important when large amounts of data are to be transferred between the client and server.

    This chapter will explain the various strategies available to handle multiple clients. In addition, we’ll build servers of each type. We’ll start off with a client test program.

    Client Test Program

    A server isn’t much good without a client program to connect to it. In this chapter we’ll look at and implement several types of servers. To see how they work we’ll use a client test program. This will help us see how each server type handles multiple clients.

    To test a server you’ll need to open two xterm windows. In the first window, execute the server that you wish to test. In the second window, execute the client test program. You should see output in both the server and client windows.

    Here’s our test client program, client.c. We’ll use it to test the various server examples throughout this chapter. First, we include the needed system header files:

    /* client.c * /
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>

    We’ll use the fork() system call to generate a number of child processes to simulate multiple clients connecting to the server at the same time. This is the forward declaration of the process function:

    void child_func(int childnum);

    This is our main() function. We check the command line to see how many child processes to create.

    int main(int argc, char *argv[])
    {
     
    int nchildren = 1;
     
    int pid;
     
    int x;
     
    if (argc > 1) {
        nchildren = atoi(argv[1]);
      }

    Next, we loop and create the specified number of children. We will look at this later, but if fork() returns 0, then it has returned in the child process, so we call our child function.

      for (x = 0; x < nchildren; x++) {
       
    if ((pid = fork()) == 0) {
         
    child_func(x + 1);
         
    exit(0);
       
    }
      }

    Once we’ve created all of the children, the parent process waits for them to finish before returning.

      wait(NULL);
      return 0;
    }

    Next, we create our child function. This is where we connect to the server.

    void child_func(int childnum)
    {
      int sock;
      struct sockaddr_in sAddr;
      char buffer[25];

    We create our client socket and bind it to a local port.

      memset((void *) &sAddr, 0, sizeof(struct sockaddr_in));
      sAddr.sin_family = AF_INET; 
      sAddr.sin_addr.s_addr = INADDR_ANY;
      sAddr.sin_port = 0;
     
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      bind(sock, (const struct sockaddr *) &sAddr, sizeof(sAddr));

    Then we attempt to connect to whichever server is running on the local machine.

      sAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
      sAddr.sin_port = htons(1972);
     
    if (connect(sock, (const struct sockaddr *) &sAddr, sizeof(sAddr)) != 0) {
        perror("client");
        return;
     
    }

    Once connected, we send some characters to the server and read what the server sends back. We also insert some pauses, using sleep() to keep the clients from connecting and disconnecting so quickly that we don’t have more than one connected to a server at the same time.

      snprintf(buffer, 128, "data from client #%i.", childnum);
      sleep(1);
      printf("child #%i sent %i chars\n", childnum, send(sock, buffer,
            
    strlen(buffer), 0));
      sleep(1);
      printf("child #%i received %i chars\n", childnum,
            
    recv(sock, buffer, 25, 0));

    Finally, we close the connection and return.

      sleep(1);
      close(sock);
    }

    The test client can be compiled with the following command:

    $>gcc -o client client.c

    This runs the client with five child processes, each connecting to the server.

    $>./client 5



     
     
    >>> More Administration Articles          >>> More By Apress Publishing
     

       

    ADMINISTRATION ARTICLES

    - Network Booting via PXE: the Basics
    - Scalix: Linux Administrator`s Guide
    - Network Administration with FreeBSD 7
    - Components of an Information Architecture
    - The Anatomy of an Information Architecture
    - Configuring Load-Balanced Clusters
    - Load-Balanced Clusters
    - UNIX Time Format Demystified
    - Making Changes in the CVS
    - Building Your First CVS Repository
    - CVS Quickstart Guide
    - Authorizing Users in Samba
    - Handling User Accounts in Samba
    - Authentication in Samba
    - Accounts, Authentication, and Authorization





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT