Reputation: 2625
I'm trying to check for an host on a network by performing an non-blocking connect and then performing an select to see whether the socket is writable or under-exceptions .I try to establish an socket connection over the ports 80,139 .The host will be discoverable if the socket is writable after connect or when it goes to exceptions when the host sends an RST pack et.
I had written an code using windows sockets and the logic worked fine ,but using linux sockets the program is not giving the desired results .The select function returns 1 for any given ip address's even though there are no hosts on that ip .The select would have timed out on the winsock's case returning an 0.I have written the code below ,let me know where exactly is the problem.
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int port[]={80,139};
void Free(int Sock_Arr[])
{
for(int i=0;i<2;i++)
{
close(Sock_Arr[i]);
}
return ;
}
int main()
{
int Socket[2],result=0; //Socket array
struct sockaddr_in service;
fd_set writefds;
fd_set exceptfds;
struct timeval timer;
timer.tv_sec=5;
timer.tv_usec=0;
int flag=0;
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
char Ip_Addr[20];
for(int i=0;i<2;i++)
{
if((Socket[i]=socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
{
Free(Socket);
}
fcntl(Socket[i],F_SETFL,O_NONBLOCK);
}
bzero(&service, sizeof(sockaddr_in));
printf("Enter the ip-address : ");
scanf("%s",Ip_Addr);
service.sin_family=AF_INET;
service.sin_addr.s_addr=inet_addr(Ip_Addr);
for(int i=0;i<2;i++)
{
FD_SET(Socket[i],&writefds);
FD_SET(Socket[i],&exceptfds);
service.sin_port=htons((unsigned short int )port[i]);
connect(Socket[i],(struct sockaddr *)&service,sizeof(sockaddr_in));
result= select(Socket[i]+1,NULL,&writefds,&exceptfds,&timer);
if(result<0||result==0)
{
flag=0;
printf("\n The machine could not be found on the port %d ",port[i]);
printf("result : %d",result);
perror("select");
}
else
{
printf("\n The machine could be found on the port %d ",port[i]);
flag=1;
printf("result : %d",result);
if(FD_ISSET(Socket[i],&writefds))
{
printf("The socket triggered on write on port %d",port[i]);
}
else if(FD_ISSET(Socket[i],&exceptfds))
{
printf("The socket triggered on except on port %d",port[i]);
}
else
{
printf("No socket triggered on %d",port[i]);
}
}
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
}
Free(Socket);
if(flag==1)
{
return 1;
}
else
{
return 0;
}
}
Upvotes: 1
Views: 205
Reputation: 21351
Here
result= select(Socket[i],NULL,&writefds,&exceptfds,&timer);
the first argument to select
should be the largest file descriptor you want to select()
on + 1. As you are only l You are not adding 1 and that could cause a problem. Try
result= select(Socket[i]+1,NULL,&writefds,&exceptfds,&timer);
You would be better off actually NOT having a loop over your sockets and add ALL the socket file descriptors to the fd_sets, working out the largest file descriptor, perform all the non blocking connect
calls and then use your select call just once to check for socket activity on any of them (using the largest file descriptor +1 as the first argument to select). Then if select()
returns positive you can use FD_ISSET
to identify what socket caused select()
to trigger; This way you can use select()
to look for activity over many sockets at once. This is how I do things when I am listening for activity on multiple sockets.
At the very least you should probably clear your fd_set each time you iterate over your second loop in which you perform the connect()
calls as you are not removing the socket fds that you added in previous iterations and so you may be looking for activity on other sockets in addition to the currently added one.
Also, doing this in the way you are doing, you are not resetting your timeout values you send to the select()
call. From the select
man pages it clearly states that select
may change the timeout value. Thus if this is the case it is possible that your timeout has been reduced by subsequent iteration calls to select
try resetting the timeout to 5 seconds at each iteration also. If the timeout has been reduced so much that it is zero, then the select() call will return instantly (polling).
Upvotes: 1