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_INE T,SOCK_STR EAM,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(serv er_addr));
server_addr.sin_family=AF_ INET;
server_addr.sin_port= htons((unsigned short)Port_number);
server_addr.sin_addr.s_add r = 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_a ddr);
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,&stXcp tFDs))
{
err_ret("some exception occured \n");
exit(0);
}
if(FD_ISSET(sock_des,&stXc ptFDs))
{
err_ret("some other exception occured \n");
exit(0);
}
}
if(FD_ISSET(sock_des,&stRe adFDs))//p roblem here....
{
new_sock_des=accept(sock_d es,(struct sockaddr *)&client_addr,(unsigned int*)&client_len);
if(new_sock_des<0)
{
err_ret("Spotsd :accept not successful");
continue;
}
CallProcessRequest(sock_de s,new_sock _des,clien t_addr);
}
else if(FD_ISSET(sockfdu,&stRea dFDs))
AutoDetectSendMessage(sock fdu);
} /* End of while */
}
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)!=
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_INE
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(serv
server_addr.sin_family=AF_
server_addr.sin_port= htons((unsigned short)Port_number);
server_addr.sin_addr.s_add
/* 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_a
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,&stXcp
{
err_ret("some exception occured \n");
exit(0);
}
if(FD_ISSET(sock_des,&stXc
{
err_ret("some other exception occured \n");
exit(0);
}
}
if(FD_ISSET(sock_des,&stRe
{
new_sock_des=accept(sock_d
if(new_sock_des<0)
{
err_ret("Spotsd :accept not successful");
continue;
}
CallProcessRequest(sock_de
}
else if(FD_ISSET(sockfdu,&stRea
AutoDetectSendMessage(sock
} /* End of while */
}
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
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
Hey you need to do "FD_ZERO " before calling select each time in the loop ....
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
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
ASKER
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
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 !!
how about the else part ... place a print in the else part ... may be the fd is not set !!
ASKER
The else part is always successful.(the one which checks for udp). I found that it always goes into the function AutoDetectSendMessage...
Balaji
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)
if that is not the correct behaviour for your application, look for logical errors (big pain)
ASKER
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)
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
Make sure that
sock_des < FD_SETSIZE && sockfdu < FD_SETSIZE
ASKER
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
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 !!!
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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()