#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2003
    Posts
    16
    Rep Power
    0

    Linux Socket Programming : How to Handle Mutliple Client in C++ (coding)


    hi all,

    can anyone give a exmple code how a server can handle multiple clients in same time.server and client are in linux enviroment and i' using c++.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    33
    Rep Power
    15
    I would recommend.

    ACE

    It is portable across most common platforms. And they simplify using sockets. ( At least in my opinion) They have many examples on the site, and a fairly extensive help. There are also a few books dedicated to ACE.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Posts
    33
    Rep Power
    15
    I would recommend.

    ACE

    It is portable across most common platforms. And they simplify using sockets. ( At least in my opinion) They have many examples on the site, and a fairly extensive help. There are also a few books dedicated to ACE.
  6. #4
  7. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    98
    here's some old code i found lying around. looks like it needs some work, but it should give you the general idea.. the classic way to handle multiple tcp clients, fork a child to handle each client. your other option and slightly more complex is to use select() which imo is a better option if you're not dealing with too many clients. if you want to see a select version as well, tell me and i'll post it.
    Code:
    #include <my_sock.h>
    #include <errno.h>
    
    #define PORT 6969
    #define MAXLINE 500
    
    int main(int argc, char **argv)
    {
            int     childpid = 0, s_listen = 0, s_conn = 0;
            char    recv_buf[MAXLINE + 1], send_buf[MAXLINE + 1], buff[MAXLINE];
            struct  sockaddr_in     servaddr, clientaddr;
            socklen_t len = sizeof(clientaddr);
    
            //initialize the socket -- returns < 0 on error
            if ( (s_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            {       printf("socket creation error\n");      exit(errno);    }
    
            //setup the sock_addrin structure
            memset(&servaddr, 0, sizeof(servaddr));
            memset(&clientaddr, 0, sizeof(clientaddr));
            servaddr.sin_family = AF_INET;
            servaddr.sin_port   = htons(PORT);
            servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
            //bind socket 
            if( (bind(s_listen, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0)
            {       printf("bind error\n"); exit(errno);    }
    
            //go into listen mode
            if( (listen(s_listen, 5)) < 0)
            {       printf("listen error\n");       exit(errno);    }
    
            while(1)        //accept loop
            {
                    //accept a connection
                    if( (s_conn = accept(s_listen, (struct sockaddr *) &clientaddr, &len)) < 0)
                    {       printf("accept error\n");       exit(errno);    }
    
                    //print out client data
                    printf("Connection from %s, port %d\n",
                                    inet_ntop(AF_INET, &clientaddr.sin_addr, buff, sizeof(buff)),
                                    ntohs(clientaddr.sin_port));
                    //fork a child process to handle client
                    if( (childpid = fork()) == 0)
                    {       //child process
                            close(s_listen);
                            while(1)        //send/recieve loop
                            {
                                    //clear buffers
                                    bzero(recv_buf, MAXLINE);       bzero(send_buf, MAXLINE);
                                    
                                    //echo back to client, returns number bytes sent or < 0 on error
                                    if( (send(s_conn, send_buf, strlen(send_buf), 0)) <= 0)
                                    {       printf("send error\n");         exit(errno);    }
    
                            }
                    }
                    else if(childpid < 0)
                    {
                            printf("fork error\n"); exit(errno);
                    }
                    //close connected socket
                    close(s_conn);
            }
            //cleanup
            close(s_conn);
    }
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2003
    Posts
    16
    Rep Power
    0
    i downloaded already ACE, buti dunno how to install and configure it..

    infamous41md..

    thanks 4 the code..its not really work smoothly... can u post a code using select..
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,325
    Rep Power
    2226
    For using select, here's a tcp echo server using select. Source code is the example from the web site, http://cs.baylor.edu/~donahoo/PocketSocket/ , of Donahoo and Calvert's book, "The Pocket Guide to TCP/IP Sockets: C Version" (AKA "TCP/IP Sockets in C: Practical Guide for Programmers"). They also have examples of a server using threads and forking. You'll need to download one or two more files from their site to get this example to make.
    Code:
    #include "TCPEchoServer.h"  /* TCP echo server includes */
    #include <sys/time.h>       /* for struct timeval {} */
    #include <fcntl.h>          /* for fcntl() */
    
    int main(int argc, char *argv[])
    {
        int *servSock;                   /* Socket descriptors for server */
        int maxDescriptor;               /* Maximum socket descriptor value */
        fd_set sockSet;                  /* Set of socket descriptors for select() */
        long timeout;                    /* Timeout value given on command-line */
        struct timeval selTimeout;       /* Timeout for select() */
        int running = 1;                 /* 1 if server should be running; 0 otherwise */
        int noPorts;                     /* Number of port specified on command-line */
        int port;                        /* Looping variable for ports */
        unsigned short portNo;           /* Actual port number */
    
        if (argc < 3)     /* Test for correct number of arguments */
        {
            fprintf(stderr, "Usage:  %s <Timeout (secs.)> <Port 1> ...\n", argv[0]);
            exit(1);
        }
    
        timeout = atol(argv[1]);        /* First arg: Timeout */
        noPorts = argc - 2;             /* Number of ports is argument count minus 2 */
    
        /* Allocate list of sockets for incoming connections */
        servSock = (int *) malloc(noPorts * sizeof(int));
        /* Initialize maxDescriptor for use by select() */
        maxDescriptor = -1;
      
        /* Create list of ports and sockets to handle ports */
        for (port = 0; port < noPorts; port++)
        {
            /* Add port to port list */
            portNo = atoi(argv[port + 2]);  /* Skip first two arguments */
    
            /* Create port socket */
            servSock[port] = CreateTCPServerSocket(portNo);
    
            /* Determine if new descriptor is the largest */
            if (servSock[port] > maxDescriptor)
                maxDescriptor = servSock[port];
        }
    
        printf("Starting server:  Hit return to shutdown\n");
        while (running)
        {
            /* Zero socket descriptor vector and set for server sockets */
            /* This must be reset every time select() is called */
            FD_ZERO(&sockSet);
            /* Add keyboard to descriptor vector */
            FD_SET(STDIN_FILENO, &sockSet);
            for (port = 0; port < noPorts; port++)
                FD_SET(servSock[port], &sockSet);
    
            /* Timeout specification */
            /* This must be reset every time select() is called */
            selTimeout.tv_sec = timeout;       /* timeout (secs.) */
            selTimeout.tv_usec = 0;            /* 0 microseconds */
    
            /* Suspend program until descriptor is ready or timeout */
            if (select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimeout) == 0)
                printf("No echo requests for %ld secs...Server still alive\n", timeout);
            else 
            {
                if (FD_ISSET(0, &sockSet)) /* Check keyboard */
                {
                    printf("Shutting down server\n");
                    getchar();
                    running = 0;
                }
    
                for (port = 0; port < noPorts; port++)
                    if (FD_ISSET(servSock[port], &sockSet))
                    {
                        printf("Request on port %d:  ", port);
                        HandleTCPClient(AcceptTCPConnection(servSock[port]));
                    }
            }
        }
    
        /* Close sockets */
        for (port = 0; port < noPorts; port++)
            close(servSock[port]);
    
        /* Free list of sockets */
        free(servSock);
    
        exit(0);
    }
  12. #7
  13. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    98
    yea if you want my code to work correct you'll need this header,
    Code:
    //      internet header files
    /*
    #ifdef WANT_BSD
            #define __FAVOR_BSD
    #endif
    */
    #include        <arpa/inet.h>   /* inet(3) functions */
    #include        <asm/errno.h>
    #include        <asm/ioctl.h>
    #include        <errno.h>
    #include        <fcntl.h>               /* for nonblocking */
    #include        <in_cksum.h>
    #include        <linux/if.h>
    #include        <linux/filter.h>        //for socket filters
    #include        <linux/socket.h>
    #include        <linux/sockios.h>
    #include        <net/ethernet.h>       //ether_addr header
    #include        <netinet/in_systm.h>
    #include        <netinet/ip.h>
    #include        <netinet/ip_icmp.h>
    #include        <netinet/tcp.h>
    #include        <netinet/udp.h>
    #include        <netinet/in.h>  /* sockaddr_in{} and other Internet defns */
    #include        <netdb.h>
    #include        <sys/types.h>   /* basic system data types */
    #include        <sys/socket.h>  /* basic socket definitions */
    #include        <sys/time.h>    /* timeval{} for select() */
    #include        <sys/stat.h>    /* for S_xxx file mode constants */
    #include        <sys/uio.h>             /* for iovec{} and readv/writev */
    #include        <sys/wait.h>
    #include        <sys/un.h>            
    #include        <signal.h>
    #include        <stdio.h>
    #include        <stdlib.h>
    #include        <string.h>
    #include        <unistd.h>
    #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
           #include <netpacket/packet.h>
           #include <net/ethernet.h>     /* the L2 protocols */
           #else
           #include <asm/types.h>
           #include <linux/if_packet.h>
           #include <linux/if_ether.h>   /* The L2 protocols */
    #endif
    //      tcp flags               need to use BSD style tcp header for these #define __FAVOR_BSD to enable it b4 linking 2 librar
    y
    #define         TCP_FIN         0x01
    #define         TCP_SYN         0x02
    #define         TCP_RST         0x04
    #define         TCP_PUSH        0x08
    #define         TCP_ACK         0x10
    #define         TCP_URG         0x20
    
    //      internet headers
    #define         IP_HDRLEN       20              //duhhh
    #define         ICMP_HDRLEN     8
    #define         TCP_HDRLEN      20
    #define         UDP_HDRLEN      8
    #define         ETH_HDRLEN      14
    
    //      useful defines
    #define         ETH_BUFSIZE     1500            //max size of ethernet frame w/o header
    #define         ADDR_LEN        16              //max len of ascii ip address + NULL terminator
    
    //      LSF OFFSETS     these are also useful for otther stuff  as they contain the exact byte offsets off
    //                      almost all of the header fields. useful to get a value quickly 
    #define         LSF_IP_V        0x0     //for consistency       ../ mask 0xf0  }  to get these 4 bit values we use
    #define         LSF_IP_HL       0x0     //..                    ../ mask 0x0f  }  these masks with bitwise & 
    #define         LSF_IP_TOS      0x1
    #define         LSF_IP_TL       0x2
    #define         LSF_IP_ID       0x4
    #define         LSF_IP_FL       0x6
    #define         LSF_IP_TTL      0x8
    #define         LSF_IP_P        0x9
    #define         LSF_IP_CS       0xa
    #define         LSF_IP_SIP      0xc
    #define         LSF_IP_DIP      0x10
    
    #define         LSF_UDP_SP      0x0
    #define         LSF_UDP_DP      0x2
    #define         LSF_UDP_L       0x4
    #define         LSF_UDP_CS      0x6
    #define         LSF_TCP_SP      0x0
    #define         LSF_TCP_DP      0x2
    #define         LSF_TCP_SQ      0x4
    #define         LSF_TCP_AK      0x8
    #define         LSF_TCP_HL      0xc
    #define         LSF_TCP_FL      0xd
    #define         LSF_TCP_WN      0xe
    #define         LSF_TCP_CS      0x10
    #define         LSF_TCP_UR      0x12
    
    #define         LSF_E_P         0xc
    
    #define         PS_LEN          0xc
    //each of these is bitwise OR'ed to match TCP flags
    #define FIN_M           0x01    //...notice the pattern? i hope so! since each flag represents a single bit
    #define SYN_M           0x02    //we test for the exact number that indicates that power of 2
    #define RST_M           0x04
    #define PSH_M           0x08
    #define ACK_M           0x10
    #define URG_M           0x20
    
    //useful port numbers in hex
    #define TLNT            0x17            //23            port numbers in hex
    #define FTP             0x15            //21
    #define SMTP            0x19            //25
    #define POP             0x6e            //110
    #define TFTP            0x45            //69
    #define HTTP            0x50            //80
    
    #define LEN(x) (sizeof(x)/sizeof(struct sock_filter))   //macro for getting code length
    
    //      useful structures               //need to rename pseudohdr to tcp_ps b/c we have a udp one as well to make
    struct pseudohdr                //tcp pseudo header used in calculating checksum
    {
            struct in_addr saddr;   //ip source address             04 bytes
            struct in_addr daddr;   //ip destination address        04 bytes
            u_char pad;             //padding                       01 bytes
            u_char protocol;        //protocol                      01 bytes
            u_short length;         //tcp total length              02 bytes        --->> sum of this 12 bytes
            struct tcphdr tcpheader;        //tcpheader             20 bytes
    };

IMN logo majestic logo threadwatch logo seochat tools logo