• C

FD_ISSET macro fails...

Hi all,

I have a client server program. I am using both tcp and udp. The udp part is to basically tell a client that a server is running on that machine.The problem is that the third call to FD_ISSET fails(I have marked this with a comment //problem here). I would like to know why this is happening.Due to this reason none of the clients are able to contact the server. Can anybody help me out...The main loop of the server code is pasted below.

regards
balaji

int MainLoop(void)
{
      int client_len=0,       
                new_sock_des=0,
                sock_des=0,
      child_pid=0,
                retval=0,
                sock_opt;
         
        int   sockfdu; /*UDP socket*/
   
       char localhost[MAXHOSTNAME+1],
       display[50];
       struct hostent *hp;
       struct sockaddr_in   server_addr,
                client_addr;
        fd_set stReadFDs;
        fd_set stXcptFDs;
 

      if(InitSocket(localhost)!=TRUE)
          exit(1);

/* Get the host name and other info on which this server is run */
     if((hp = gethostbyname(localhost)) == NULL)
         err_sys("Socket Error:Cant get localhost info");

 /*Create a tcp socket */
    if((sock_des=socket(AF_INET,SOCK_STREAM,0))<0)
       err_sys("Socket Error:Cant create TCP Socket");

   /*Create a udp socket */
   if( (sockfdu = socket (AF_INET, SOCK_DGRAM,IPPROTO_UDP)) <0)
      err_sys("Socket Error:Cant create UDP Socket\n");  

     memset((char *) &server_addr,0,sizeof(server_addr));
     server_addr.sin_family=AF_INET;
     server_addr.sin_port= htons((unsigned short)Port_number);
     server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
      
/* Tell the system to allow local addresses to be reused. */
     sock_opt = 1;
if (setsockopt(sock_des, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt,sizeof (sock_opt)) == -1) {
         (void) close(sock_des);
         //return (-1);
 }


  /* Bind to the address and listen on tcp socket */
   if(bind(sock_des,(struct sockaddr *)&server_addr, sizeof(server_addr))<0)
       err_sys("Socket Error:TCP bind not successful,port no %d used by some other application",Port_number);

     
   listen(sock_des,Q_LEN);

   /* Bind to the address and listen on udp socket */
   if (bind(sockfdu, (struct sockaddr *) &server_addr, sizeof(server_addr)))
       err_sys("Socket Error:UDP bind not successful,port no %d used by some other application",Port_number);

      
   client_len=sizeof(client_addr);
      
   FD_ZERO(&stReadFDs);
   FD_ZERO(&stXcptFDs);
   FD_SET(sockfdu,&stReadFDs);
   FD_SET(sockfdu,&stXcptFDs);
   FD_SET(sock_des,&stReadFDs);
   FD_SET(sock_des,&stXcptFDs);
   

while(1)
{

     errno=0;
     retval=select(FD_SETSIZE,  &stReadFDs, NULL, &stXcptFDs, NULL);
         
      if(errno == EINTR)
      {
         FD_ZERO(&stReadFDs);
         FD_ZERO(&stXcptFDs);
         FD_SET(sockfdu,&stReadFDs);
         FD_SET(sockfdu,&stXcptFDs);
         FD_SET(sock_des,&stReadFDs);
         FD_SET(sock_des,&stXcptFDs);
         continue;
      }
   if(retval == -1)
   {
           perror("problem with select");
               exit(0);
   }
   else if (retval!=0)
   {
        if(FD_ISSET(sockfdu,&stXcptFDs))
         {
             err_ret("some exception occured \n");
             exit(0);
         }
        if(FD_ISSET(sock_des,&stXcptFDs))
        {
           err_ret("some other exception occured \n");
           exit(0);
         }
}

if(FD_ISSET(sock_des,&stReadFDs))//problem here....
{
 new_sock_des=accept(sock_des,(struct sockaddr *)&client_addr,(unsigned int*)&client_len);
  if(new_sock_des<0)
   {
      err_ret("Spotsd :accept not successful");
      continue;
   }
         
   CallProcessRequest(sock_des,new_sock_des,client_addr);
      
          
}
 else if(FD_ISSET(sockfdu,&stReadFDs))
         AutoDetectSendMessage(sockfdu);

  }  /* End of while */
}
balajis79Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

sunnycoderCommented:
you call select and then you call FD_SET ?

it is the other way round ... you need FD_SET before select and also keep in mind that you need to set the FDs again before you call select()
0
sunnycoderCommented:
oops sorry ... I did not read carefully

anyway... you need to move the FD_SET staements inside the loop

from the man page
  On  success,  select  and  pselect  return  the number of descriptors contained in the descriptor sets, which may be zero if the timeout expires

so else if (retval != 0) would represent success and == 0 would represent time out ... so you need a bit of reorganization there
0
AjarCommented:
Hey you need to  do  "FD_ZERO " before calling select each time in the loop ....

0
Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

sunnycoderCommented:
reorganize to something like this ....
while(1)
{

 FD_ZERO(&stReadFDs);
  FD_ZERO(&stXcptFDs);
  FD_SET(sockfdu,&stReadFDs);
  FD_SET(sockfdu,&stXcptFDs);
  FD_SET(sock_des,&stReadFDs);
  FD_SET(sock_des,&stXcptFDs);

    errno=0;
    retval=select(FD_SETSIZE,  &stReadFDs, NULL, &stXcptFDs, NULL);
       
      if(errno == EINTR)
     {
/*        FD_ZERO(&stReadFDs);
        FD_ZERO(&stXcptFDs);
        FD_SET(sockfdu,&stReadFDs);
        FD_SET(sockfdu,&stXcptFDs);
        FD_SET(sock_des,&stReadFDs);
        FD_SET(sock_des,&stXcptFDs);  */
        continue;
     }
  if(retval == -1)
  {
         perror("problem with select");
             exit(0);
  }
  else if (retval == 0)
  {
      /* time out will never happen since you gave NULL*/
 }
else
  {
       if(FD_ISSET(sockfdu,&stXcptFDs))
        {
            err_ret("some exception occured \n");
            exit(0);
        }
       if(FD_ISSET(sock_des,&stXcptFDs))
       {
          err_ret("some other exception occured \n");
          exit(0);
       
      if(FD_ISSET(sock_des,&stReadFDs))//problem here....
      {
       new_sock_des=accept(sock_des,(struct sockaddr *)&client_addr,(unsigned int*)&client_len);
        if(new_sock_des<0)
         {
                  err_ret("Spotsd :accept not successful");
                 continue;
         }
       
       CallProcessRequest(sock_des,new_sock_des,client_addr);              
     }

     else if(FD_ISSET(sockfdu,&stReadFDs))
        AutoDetectSendMessage(sockfdu);
 } /*end of else*/
  }  /* End of while */
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
balajis79Author Commented:
Dear Sunnycoder,

I tried out your solution but it did not solve the problem. Actually i forgot to mention something important last time. I am porting this code to run on netware 6.5 as an nlm (akin exe). When i run this piece of code on the netware server the problem occurs...

Balaji
0
sunnycoderCommented:
Ok, keep the FD_SETs inside the loop anyway...
FD_ISSET ia a macro... how did you deduce that this was the call that was failing ? may be the FD was really not set
0
balajis79Author Commented:
I put printf's after each statement to trace the flow(Unfortunately this is the only way to debug on a netware server). I found that it was never printing the one inside " if(FD_ISSET(sock_des, &stReadFDs))". Hence i deduced that this might be the problematic statement. (Actually i am new to socket programming...so please tell me if i have made any other error also). The FD_SETs part is duly noted.

Balaji
0
sunnycoderCommented:
>I found that it was never printing the one inside " if(FD_ISSET(sock_des, &stReadFDs))
how about the else part ... place a print in the else part ... may be the fd is not set !!
0
balajis79Author Commented:
The else part is always successful.(the one which checks for udp). I found that it always goes into the function AutoDetectSendMessage...
Balaji
0
sunnycoderCommented:
that would mean that sock_des is not set while sockfdu is set ... does not look like select() or FD_ISSET error...
 if that is not the correct behaviour for your application, look for logical errors (big pain)
0
balajis79Author Commented:
but when i print the sock_des value i get 6. Does is not mean that the sock_des is correct. In that case should it not get set?
0
sunnycoderCommented:
sock_des holds the int value by which system identifies this socket
FD_ISSET will show it set if and only if there was some activity at that socket (send/recv)
0
mtmikeCommented:
Your socket descriptors might be out of range. Netware has a FD_SETSIZE=16.

Make sure that
sock_des < FD_SETSIZE && sockfdu < FD_SETSIZE
0
balajis79Author Commented:
Dear mtmike,

I saw that FD_SETSIZE is set to 64 in select.h. Even other wise i get the values 6 & 7 for sock_des(tcp) and sockfdu(udp) respectively. So it is less than 16.

balaji

0
sunnycoderCommented:
sock_des and sockfdu are nothing but descriptors and have nothing to do with SETSIZE

from the man page
   The functions select and pselect wait for a number of file descriptors to change status.

so FD_ISSET will evaluate to true if there was a change in status... e.g. on a readfd, some data arrived.... it has nothing to do with actual value of the fd !!!
0
mtmikeCommented:
On unix, socket/file descriptors are small integers and the fd_set structure is implemented as a bit set of some fixed size. The first argument to select is the highest numbered file descriptor in any of the three sets, plus one.

On netware, this function seems to be different:
http://developer.novell.com/ndk/doc/libc/index.html?page=/ndk/doc/libc/libc_enu/data/sdk86.html

I would try changing the first argument to select to 3 (2+1).

Also, check the return value of listen().

And, do make the changes sunnycoder suggested.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.