You are here:

C++/Solaris - select() returns -1....

Advertisement


Question
My program does close the socket after use (each socket can remain maximum of 20 seconds before close() is being called - most of the time close() is being called after 3 or 4 seconds of openning the socket). When I check with netstat it also shows me not more than 5 sockets open at a given time. So every indication is that I am closing the socket descriptors properly. But still the next "socket()" call returns yet another different socket descriptor. Like I mentioned earlier, I see this behavior only on Solaris. I didn't have this issue on either Linux or AIX.

Regards,

- Bimal

-------------------------
Followup To
Question -
But doesn't solaris reuse the file descriptor values when that descriptor is no longer is in use (ie. when that socket is explicitly closed)? It seem to happen in AIX (ie. socket descriptors returned from repeated "socket()" calls doesn't increase - They appear to be static with a value of "8" on AIX).

I tried using setsockopt with SO_REUSEADDR thinking that it might have some effect on the socket descriptor - but it didn't help. Is there an option on "socket()" call that will help me? I'm kinda desperate here...

Thanks.


-------------------------
Followup To
Question -
Hi,

I just found out the issue was that my TCP client's "socket()" call always returns an incremented descriptor value (ie, 1, 2, 3, 4,...etc). So when it hits 1024, my select() fails because it won't accept anything above 1024 as select() call's first parameter. In AIX, socket() call returns the descriptor number which doesn't have this incremented value. This problem occurs only in Solaris. Is there a Client Socket option I can set so that file descriptor value returned from "socket()" call doesn't increment always?

Thanks.

- Bimal

-------------------------
Followup To
Question -
Hi,

I have a multithreaded program written in gcc and is running on Solaris. It opens one TCP client connection per thread to a multi-threaded TCP server. After writing, each client thread blocks on it's own select() call (select used here purely to allow to block for given timeout period).

It works fine until it creates about 1030 sockets. At that stage "select" basically starts returning immidiately with -1. (perror says "Invalid argument"). And until I restart the client program all client threads continue with this issue. Following is the client code I use.... please help. Also is there another way I can achieve a timeout without using "select()"?


bool timeRead(char *buffer, int size, int time, int &iReadSize)
{
   fd_set rset;
   struct timeval tval;
   int result;
   initBuffer(buffer, size);

   // Initialise select related parameters.
   FD_ZERO(&rset);
   FD_SET(iSockFD, &rset);

   tval.tv_sec = time;
   tval.tv_usec = 0;

   result = select(iSockFD+1, &rset, NULL, NULL, &tval);
   if (result == 0)
   {
       cout << "Select Time out fired" << endl;
       errno = ETIMEDOUT;
       return false;
   }
   else if (result < 0)
   {
       cout << "Select error " << (int)result << endl;
       perror("System (perror) error message : ");
       return false;
   }
   else
   {
       if (FD_ISSET(iSockFD, &rset))
       {
         if ((iReadSize = read(iSockFD, buffer, size)) == -1)
         {
         cout << "Socket Read error" << endl;
         return false;
         }
         else if(iReadSize == 0)
         {
         cout << "Zero returned from read" << endl;
         return false;
         }
         else
         {
         return true;
         }
       }
       else
       {
         return false;
       }
   }

} // End function

Answer -
In your progra, there were some parameters that were undefined. You either need to send me the whole program, or check the manual for correct use of the select function.
You may also try to start from the following templete:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
   fd_set rfds;
   struct timeval tv;
   int retval;
   /* Watch stdin (fd 0) to see when it has input. */
   FD_ZERO(&rfds);
   FD_SET(0, &rfds);
   tv.tv_sec = 5; /* Wait up to five seconds. */
   tv.tv_usec = 0;
   retval = select(1, &rfds, NULL, NULL, &tv); /* Donāt rely on the value of tv now! */
   if (retval)
      printf("Data is available now.\n"); /* FD_ISSET(0, &rfds) will be true. */
   else
      printf("No data within five seconds.\n");
   return 0;
}

Answer -
This descriptor in similar to file discriptor that system generates to uniquely identify each of them. Therefore, if you have a 1024 limitation, it doesn't make any diference if you can select the number, because you cannot select repeated numbers as descriptor.
Answer -
Yes, it can be reused, but as you said yourself, only if it is no longer in use. As far as I understant, you want to have more than 1024 sockets open and so non of them can be reused. Is that anything that I am missing here?
Basically, you should let system to take care of the discriptors and reuse them itself.

Answer
I understand now. However I don't have any experience on this issue using Solaris and at the moment I doen't have access to Solaris. My suggestion is to look for a function that causes OS to reset the descriptor counter. If such function exist, it will start from 0 to find the first available free descriptor. Otherwise, you should look for some function that let you specify the socket descriptor (or its range), before the descriptor is assigned. The last option would be looking for a function that let you change socket descriptor after it is assign. OS might not let you do the last one.
I hope this helps.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Sam

Expertise

You may ask me about simple to complicated C/C++ programming methods/style and most like questions about network programming in C++.

Experience

I'm a professional programer in C++ and network/internet programming.

©2016 About.com. All rights reserved.