0

For example, I don't how many clients will connect, but I'd like for any number of clients to be able to connect during a time period, say 10 seconds.

Right now I have something like this:

unsigned int currentTime = (unsigned int)time(NULL);
int session[100], sessionCount = 0;

// accept connections for 10 seconds:
while ( (unsigned int)time(NULL) - currentTime < 10 ) {
   session[sessionCount++] = accept( my_sock_desc, (struct sockaddr *)&client_sock_addr, &sock_size );
}

This will accept any number of connections, but obviously, the last iteration of the while loop will leave a call to accept() blocking the program from continuing.

How would I solve this problem?

trusktr
  • 44,284
  • 53
  • 191
  • 263

2 Answers2

2

You want to use select or poll with a timeout value to detect if it is safe to call accept without it blocking.

void mainloop()
{
    time_t startTime = time(NULL);
    time_t listenTime = 10; // 10 seconds, for example
    time_t elapsed = 0;

    elapsed = time(NULL) - startTime;
    secondsToWait = (elapsed >= listenTime) ? 0 : (listenTime-elapsed);
    while (secondsToWait > 0)
    {
        fd_set readset = {};
        FD_SET(my_sock_desc, &readset);
        timeval waittime = {};
        waittime.tv_sec = secondsToWait;
        int count = select(my_sock_desc+1, &readset, NULL, NULL, &waittime);
        if (FD_ISSET(my_sock_desc, &readset))
        {
            accept( my_sock_desc, (struct sockaddr *)&client_sock_addr, &sock_size );
        }

        elapsed = time(NULL) - startTime;
        secondsToWait = (elapsed >= listenTime) ? 0 : (listenTime-elapsed);
    }
}
selbie
  • 100,020
  • 15
  • 103
  • 173
  • Does this mean that `accept()` gets called only after a client has called `connect()`? – trusktr Dec 27 '12 at 12:15
  • Yes, `select()` will report when the listening socket has a pending client connection waiting to be accepted. – Remy Lebeau Dec 27 '12 at 21:54
  • Is there a way to do another task while we wait for the connections, still without threads? – trusktr Dec 30 '12 at 06:39
  • There's the old school unix way (before threads were a part of unix) - You can create a signal handler for SIGIO, and then call fcntl (with F_SETOWN flag) on the listening socket. When there's an incoming connection your running program will get "signaled" (interrupted) for your signal handler function to run. You could "accept" a new connection in your signal handler. But this approach is error prone and messy in my opinion. For purposes of debugging and maintainability, you are better off just using a dedicated thread. IMHO. BTW, I never actually tried this approach. Just read about it. – selbie Dec 30 '12 at 08:13
1

check server code here

pseudo code:

listener thread:
       while(1)
        {
        :
        : 
        if(select(...)>0)
        {
        if(FD_SET(..)) 
                  if(accept(...)) dispatch_msg_to_processing_thread;
        }
        :
        :
        }

processing thread: process message.
  • The example does the processing right there. Why do you want to avoid threads? –  Dec 29 '12 at 05:15
  • I had never used them before, but I dove in and made it happen with threads. :D @selbie's answer is also interesting, without the use of threads. – trusktr Dec 30 '12 at 06:38