Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

multi threaded server

Status
Not open for further replies.

axman505

Technical User
Jun 20, 2001
489
US
I am trying to code a multi threaded echo server for a exercise, but its is causing me some problems. I am having trouble trying to figure out how to code it in a way it could accept unlimited number of clients. From what ive seen, I will need to set some max number of threads.

Code:
main(int argc, char *argv[])
{
        connection      *conn;
        pthread_t t[THREADS];
        int i;

        if (argc != 2) {
                (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);
                exit(1);
        }
        /* wait for a connection from an echo client */
        *conn = await_contact((appnum) atoi(argv[1]));
        if (*conn < 0)
                exit(1);
    
        while(1){
                pthread_create(&t[i], NULL, make_server, (void*) conn);
                pthread_join(t[i], NULL);
        }
        return 0;

}

Can anyone offer me any suggestions?
 
Well the loop should be along the lines of
Code:
while ( 1 ) {
  // find a free t[i]
  // wait for a connection
  // create the thread
  // examine all threads to see which can be joined, and make those free again
}

--
 
Threads are always interesting, no matter the implementation.
Any way you approach this it's going to be fun to
implement a server with a dynamic thread pool.

Here is an unfinished code snippet of how I might approach
it. I'm sure there are better ideas and solutions. ;)
Code:
#define ESRVPORT 2100
#define MAXQ 10
#define BSZ 125

struct clientdata
{
  int socket;
  struct sockaddr_in *pt;
};

static int CONNECTS = 0;
int allocThread (pthread_t *);
void *handleClient (void *);
int freeResources (int);

int
main (void)
{
  int sock, sock1, len, ind;
  struct sockaddr_in server, client;
  struct clientdata foothing;
  pthread_t *pool = NULL;


  if ((sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
      perror ("Socket() ");
      return -1;
    }
  bzero (&server, sizeof (server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = htonl (INADDR_ANY);
  server.sin_port = htons (ESRVPORT);

  bind (sock, (struct sockaddr *) &server, sizeof (server));
  listen (sock, MAXQ);
  len = sizeof (client);
  signal (10, freeResources);
  /*thread raises USR1 on exit which results in a handler
  decrementing the CONNECTS counter and cleaning up the
  allocated pool resources. Or use a syncronized thread 
  with  pthread_join to catch termination and call a 
  cleanup procedure. 
  Design suitable return data from the finished thread
  for processing in the latter case??*/
  
  for (;;)
    {
      if ((sock1 = accept (sock, (struct sockaddr *) &client, &len)) < 0)
	{
	  perror ("Accept() ");
	  return -1;
	}
      ind = allocThread (pool);
      /*all this code needs locking as is, bad design. lock_foothing()--or something witty */
      foothing.socket = sock1;
      foothing.pt = &client;
      pthread_create (&pool[ind], NULL, handleClient, (void *) &foothing);
    }
  return -1;
}

Pseudo-code really.
 
well, this is what i have right now, it's not quite function as i wish yet though

Code:
main(int argc, char *argv[])
{
        connection      *conn;
        pthread_t       thread[25];
        int             conn_count;

        conn_count = 0;

        if (argc != 2) {
                (void) fprintf(stderr, "usage: %s <appnum>\n", argv[0]);
                exit(1);
        }

        while(1){
                /* wait for a connection from an echo client */

                *conn = await_contact((appnum) atoi(argv[1]));

                if (*conn < 0)
                        exit(1);

                pthread_create(&thread[conn_count], NULL, make_connection, (void*) conn);
                pthread_join(thread[conn_count], NULL);
                conn_count++;

                //send_eof(*conn);
        }

}

it is dieing with a segmentation fault and im not quite sure why.
 
> conn_count++;
Well once this gets to 25, you're accessing array elements which don't exist.

--
 
is there an easy way to have an open ended array so it could techincally be unlimited threads?
 
Not without dynamically (re)allocating afaik.

Something like-
Code:
#define INC_THREAD 10
int CURR_THREADS = 0;
pthread_t *allocThread(pthread_t *pt) {
pthread_t *foo = NULL;

               if (pt == NULL) {
                   pt = malloc(INC_THREAD * sizeof(pthread_t));
                   CURR_THREADS = INC_THREAD;
                   return pt;
                  
               }

               if ( (foo = realloc(pt,(INC_THREAD + CURR_THREADS))) == NULL) {
                   return NULL;
               }
               CURR_THREADS += INC_THREAD;
               return foo;
}



 
> is there an easy way to have an open ended array so it could techincally be unlimited threads?
No and No
1. you can't have unlimited threads, the OS simply won't allow you to create threads ad-nauseum.
2. Sooner or later, threads will finish what they're doing and you need to "reap" them to reclaim the resources they used (for new threads yet to be created).

Look at my previous post where I said
"find a free t"




--
 
The same for any resource of course.
With threads:
Worked for a hosting provider where an apache dev
was hosting and this fellow was working with some java specific extensions. His box often went down with
an unmentionable, obscene, number of threads running,
doing raw db accesses. With threads in general:
Caveat Emptor.
 
This would lend it's self better to C++ or Java,

In C++ you can keep the threads in an object or struct that has state (know a thread is ready to be joined or not), and keep the objects/structs in an a vector, list or other STL container that dynamically resizes (you'd probably want a list).

In Java sockets and threads are a lot easier to manage. Of course you give up a little bit of speed as Java is not a native language.

If you really want to do it in C --
Code:
pthread_create(&thread[conn_count], NULL, make_connection, (void*) conn);
pthread_join(thread[conn_count], NULL);
conn_count++;
Doesn't this code lead to only connection at a time???
As I read it:
Create a thread and send it running,
Wait for it to return, then join it.
Increment Conn_count
goto the top of the loop to wait for another client

That means you're array threads isn't gaining you anything...

What you might want to is:
Code:
forever(;;)
{
 wait for a connection
 if(fork()==1) //spawn new thread check if child or parent
  {
   //do client handling stuff here
  }
 else
  {
   counter++;
   if(counter >= MAX_CONNECTIONS)
    {
     wait();
     counter--;
    }
  }
}
This isn't threaded, but multi-process... You'd need system level protections for any shared objects...
 
Well, we don't know what
Code:
await_contact((appnum) atoi(argv[1]));
is doing , but I assume it's calling accept(), in
which case the pthread handler goes off and does
it's business in the created thread. I'm not sure
why pthread_join is being used at all in this scenario.
As you note it is a very close to the traditional fork()
method.
I assume that the thread has less overhead than fork(),
could be wrong.
 
In a Win32 environment, a multi-threaded process is more efficient than multiple instances of the same single threaded process. This is because the O/S has to perform less when performing an intraprocess context switch (for when switching to another thread within the same process)than when performing a interprocess context switch (switching to a different thread in a different process).
 
Final word from me on this.
The thread should be created detached or detached in
the client handler. The state(COUNT) variable or any
shared data in general, should be made atomic or locked
with pthread_mutex_lock in the client handler.

When this is done everything behaves as expected.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top