我有一个 TCP 端口扫描器,它扫描给定 IP 上所有打开的端口,并只返回打开的端口和在其上运行的服务的名称。为此,我创建了一个套接字,将其设置为非阻塞模式,select()
如果端口超时,则表示端口关闭,否则打开。问题是我的 select() 总是超时,即使我尝试扫描打开的端口。我希望有人指出我的错误,我的逻辑不好吗?
#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/time.h>
#include <errno.h>
using namespace std;
fd_set working_set;
hostent *he;
char* protoc [2] = { "tcp","udpn" };
int port;
struct sockaddr_in servaddr;
int sendfd;
servent *srvport;
void set_nonblock(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
void set_block(int socket) {
int flags;
flags = fcntl(socket,F_GETFL,0);
assert(flags != -1);
fcntl(socket, F_SETFL, flags | ~O_NONBLOCK);
}
int main( int argc, char* argv[] )
{
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
char* host = argv[1];
char* pro = argv[2];
int portlow = atoi(argv[3]);
int porthigh = atoi(argv[4]);
fprintf(stderr, "n Scanning host=%s, protocol=%s, ports: %d -> %d \n",
host, pro, portlow, porthigh);
if(strcmp(pro, protoc[0])==0)
pro = protoc[0];
else if (strcmp(pro, protoc[1])==0)
pro = protoc[1];
else
{
herror("n specify valid protocol - tcp or udpn");
exit(-1);
}
if((he = gethostbyname(argv[1])) == NULL)
{
herror("n *** gethostbyname() failed ***n");
exit(-1);
}
/*In case TCP protocol is selected for scan, app opens streaming socket
for every port to be scanned, tries to connect to it, and if successful
it displays information about service using struct servent.
*/
if(strcmp(pro, protoc[0])==0) // tcp scan
{
for(port = portlow; port <= porthigh; port++)
{
// open stream socket
if((sendfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("*** socket(,SOCK_STREAM,) failed ***n");
exit(-1);
}
set_nonblock(sendfd);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
servaddr.sin_addr = *((struct in_addr *)he->h_addr);
int res = connect(sendfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
int ser;
if (res < 0) {
if (errno == EINPROGRESS) {
timeout.tv_sec = 0;
timeout.tv_usec = 10;
FD_SET(sendfd, &working_set);
if ((ser=select(sendfd+1, NULL, &working_set, NULL, &timeout)) > 0) {
srvport = getservbyport(htons(port), protoc[0]);
}
else {
fprintf(stderr, "Timeout or error() %d\n",ser);
perror("select(): ");
}
}
else {
fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
}
if(srvport != NULL)
printf("tport %d: %sn \n ", port, srvport->s_name);
else if (ser=0)
close(sendfd);
fflush(stdout);
}
//set_block(sendfd);
}//end of for()
}
}