tcp server using pthreads is not working...ne help plz?

Hi,

I am new to using threads in C++ though I have been wkring on C++ for past 1.5 years...I want to write a TCP server that serves multiple client connections...to start off..i have been working on a simple tcp echo server trying to understand how threads work....

this is my server code:

#include <sys/socket.h>
#include <sys/types.h>
#include <iostream>
#include <string>
#include <resolv.h>
#include <pthread.h>
#include <fcntl.h>
#include <netdb.h>

using namespace std;

void panic(char *msg);
#define panic(m)        {perror(m); abort();}


/*****************************************************************************
        *** This function makes the socket non-blocking!
*****************************************************************************/
void nonblock(int &sockfd)
{
        int opts;
        opts = fcntl(sockfd, F_GETFL);
        cout<<"in opt"<<endl;
        if(opts < 0)
                panic("fcntl(F_GETFL)\n")

        opts = (opts | O_NONBLOCK);
        if(fcntl(sockfd, F_SETFL, opts) < 0)
                panic("fcntl(F_SETFL)\n")

        cout<<"after opt"<<endl;
}

/*****************************************************************************/
/*** This program creates a simple echo server: whatever you send it, it   ***/
/*** echoes the message back.                                              ***/
/*****************************************************************************/
void *servlet(void *arg)                    /* servlet thread */
{       /* get & convert the data */
        int *client = (int*)arg;
        int n;
        char s[100];
        
        pthread_detach(pthread_self());

           /* proc client's requests */
        memset(s, '\0', 100);
        while( (n = (read(*client,s,100)) ) > 0 )
        {
                if (s[0] == 'Q')
                        break;
                printf("msg: %s", s);
                write(*client,s,n);
                memset(s, '\0', n);
        }

        close(*client);
        return 0;                           /* terminate the thread */
}

int main(int count, char *args[])
{       struct sockaddr_in addr;
        int sd, port;

        if ( count != 2 )
        {
                printf("usage: %s <protocol or portnum>\n", args[0]);
                exit(0);
        }

        /*---Get server's IP and standard service connection--*/
        if ( !isdigit(args[1][0]) )
        {
                struct servent *srv = getservbyname(args[1], "tcp");
                if ( srv == NULL )
                        panic(args[1]);
                printf("%s: port=%d\n", srv->s_name, ntohs(srv->s_port));
                port = srv->s_port;
        }
        else
                port = htons(atoi(args[1]));

        /*--- create socket ---*/
        sd = socket(PF_INET, SOCK_STREAM, 0);
        if ( sd < 0 )
                panic("socket");

        int on = 1;
        if ( (setsockopt(sd, SOL_SOCKET,  SO_REUSEADDR, (char *)&on, sizeof(on)) ) < 0 )
                panic("setsockoptions");

        /*--- bind port/address to socket ---*/
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = port;
        addr.sin_addr.s_addr = INADDR_ANY;                   /* any interface */
        if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
                panic("bind");

        /*--- make into listener with 10 slots ---*/
        if ( listen(sd, 10) != 0 )
                panic("listen")
        /*--- begin waiting for connections ---*/
        else
        {       int csd;
                pthread_t child;
                FILE *fp;
                cout<<"Here: "<<endl;

                while (1)                         /* process all incoming clients */
                {
                        csd = accept(sd, NULL, NULL);     /* accept connection */
                         if (csd > 0 )
                        {
                                cout<<"New connection accepted on socket : "<<csd<<endl;
        //                      nonblock(csd);
                                pthread_create(&child, 0, &servlet, &csd);       /* start thread */
                        }
                }
        }
        close(sd);
        pthread_exit(NULL);
}

But the server is behaving in a strange manner..It is able to handle just one client at a time. When i connect multiple clients to it, only the last connection gets the echo..as for the rest...the connections are neither closed nor the messages are echoed...the client just stalls!

One more observation....the last message given by previous client is echoed to the latest connection (i.e to the latest client)...and then no more echoes to the previous client..:frowning:

Am i missing something here? ne help is highly appreciated...:frowning:

No passers-by??? :frowning:

i think for each thread you have to make different pthread_t child like array to store that child threads in to it...

I have modified your code so that it works. In addition I removed the pthread_create() call by replacing it with a PTHREAD_CREATE_DETACHED attribute in pthread_create.

#include <sys/socket.h>
#include <sys/types.h>
#include <iostream>
#include <string>
#include <resolv.h>
#include <pthread.h>
#include <fcntl.h>
#include <netdb.h>

using namespace std;

void panic(char *msg);
#define panic(m)        {perror(m); abort();}

/* servlet thread - get & convert the data */
void *servlet(void *arg)
{
   int client = (int)arg;
   int n;
   char s[100];

   /* process client's requests */
   memset(s, '\0', 100);
   while( (n = (read(client,s,100)) ) > 0 ) {
      if (s[0] == 'Q')
              break;
      printf("msg: %s", s);
      write(client,s,n);
      memset(s,'\0', n);
   }

   close(client);
   pthread_exit(0);          /* terminate the thread */
}

int main(int argv, char *args[])
{
   struct sockaddr_in addr;
   int sd, port;
   int csd;
   pthread_t child;
   int on = 1;
   pthread_attr_t pattr;

   if ( argv != 2 ) {
       printf("usage: %s <protocol or portnum>\n", args[0]);
       exit(0);
   }

   /* Get server's IP and standard service connection */
   if ( !isdigit(args[1][0]) ) {
       struct servent *srv = getservbyname(args[1], "tcp");
       if ( srv == NULL )
           panic(args[1]);
       printf("%s: port=%d\n", srv->s_name, ntohs(srv->s_port));
       port = srv->s_port;
   } else
       port = htons(atoi(args[1]));

   /* create socket */
   sd = socket(PF_INET, SOCK_STREAM, 0);
   if ( sd < 0 )
       panic("socket");

   if ((setsockopt(sd, SOL_SOCKET,  SO_REUSEADDR, (char *)&on, sizeof(on)) ) < 0 )
      panic("setsockoptions");

   /* bind port/address to socket */
   memset(&addr, 0, sizeof(addr));
   addr.sin_family = AF_INET;
   addr.sin_port = port;
   addr.sin_addr.s_addr = INADDR_ANY;
   if (bind(sd,(struct sockaddr*)&addr, sizeof(addr)) != 0)
      panic("bind");

   /* set size of request queue to 10 */
   if (listen(sd, 10) < 0)
      panic("listen");

   /* set thread create attributes */
   pthread_attr_init(&pattr);
   pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);

   while (1) {
      cout << "Waiting for a new connection ...." << endl;
      csd = accept(sd, NULL, NULL);
      if (csd < 0)
         panic("accept");
      cout << "New connection accepted on socket: " << csd << endl;
      pthread_create(&child, &pattr, servlet, (void *)csd);
   }

   close(sd);
   exit(0);
}

Thank you, for uplowding the fixed code i did have another problem and i did findout what was going wrong with my code, tnx for your code...

I went through the above fixed code. I see that it works fine. I am just curious to know what was the problem with this and that u fixed here?