Link to home
Start Free TrialLog in
Avatar of balajis79
balajis79

asked on

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 */
}
Avatar of sunnycoder
sunnycoder
Flag of India image

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()
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
Avatar of Ajar
Ajar

Hey you need to  do  "FD_ZERO " before calling select each time in the loop ....

ASKER CERTIFIED SOLUTION
Avatar of sunnycoder
sunnycoder
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of balajis79

ASKER

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
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
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
>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 !!
The else part is always successful.(the one which checks for udp). I found that it always goes into the function AutoDetectSendMessage...
Balaji
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)
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?
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)
Your socket descriptors might be out of range. Netware has a FD_SETSIZE=16.

Make sure that
sock_des < FD_SETSIZE && sockfdu < FD_SETSIZE
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

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 !!!
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial