先把代码贴出来,详细的流程与注释明天再写
首先是服务器端的代码,程序的主体部分是客户端的多线程扫描,所以服务器端的代码编写的相对简单,没有过多的安全性检查的处理。
// my_server.cpp
// g++ my_server.cpp -o server
-
#include <stdio.h>
-
#include <string.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <unistd.h>
-
#include <arpa/inet.h>
-
-
int main (int c , char ** v)
-
{
-
struct sockaddr_in server_addr ;
-
int sockfd ;
-
-
sockfd = socket ( AF_INET , SOCK_STREAM , 0 ) ;
-
-
server_addr.sin_family = AF_INET ;
-
server_addr.sin_port = htons (1027) ;
-
inet_aton ("127.0.0.1" , &server_addr.sin_addr ) ;
-
-
bind (sockfd ,(struct sockaddr*)&server_addr , sizeof(struct sockaddr_in) ) ;
-
listen ( sockfd , 10 ) ;
-
-
for (;;) {}
-
-
return 0 ;
-
}
// 后面的代码均属于 client 端,使用Makefile 进行编译
// Makefile
-
CPPFLAGS = -O3
-
LDFLAGS = -lpthread
-
-
all: Main
-
-
clean :
-
rm -f *.o
-
-
Main: Main.o my_scanner.o
-
g++ -o $@ $^ $(LDFLAGS)
// my_scanner.h
-
// my_scanner.h
-
#ifndef MY_SCANNER_H
-
#define MY_SCANNER_H
-
-
#include <cstdio>
-
#include <cstring>
-
#include <cstdlib>
-
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <unistd.h>
-
#include <arpa/inet.h>
-
#include <errno.h>
-
-
#include <pthread.h>
-
#include <vector>
-
-
-
struct _scan_segment
-
{
-
unsigned short int from_port ;
-
unsigned short int to_port ;
-
struct in_addr scan_addr ;
-
} ;
-
-
typedef _scan_segment scanSegment ;
-
-
-
class Scanner
-
{
-
private :
-
std::vector<pthread_t> pthreadList ;
-
int threadNum ;
-
int connfd ;
-
struct in_addr scan_addr ;
-
int scan_max_port ;
-
int scan_len ;
-
-
public :
-
Scanner ( int _threadNum , struct in_addr _scan_addr , int _scan_max_port ) ;
-
-
// static int do_scan ( struct sockaddr_in ) ;
-
// void * scanner ( void *) ;
-
void run ( void ) ;
-
-
} ;
-
-
#endif // my_scanner.h
// myscanner.cpp
-
// myscanner.cpp
-
#include "my_scanner.h"
-
-
using namespace std ;
-
-
static void log_info ( const char *err_info , int location )
-
{
-
fprintf (stderr, "[error]: %s, [line]: %d\n" , err_info , location) ;
-
perror ("exit function errinfo ") ;
-
exit ( 1 ) ;
-
}
-
-
-
Scanner::Scanner ( int _threadNum , struct in_addr _scan_addr , int _scan_max_port )
-
{
-
-
threadNum = _threadNum ;
-
scan_max_port = _scan_max_port ;
-
-
-
if ( threadNum > scan_max_port )
-
threadNum = scan_max_port ;
-
-
scan_len = scan_max_port / threadNum ;
-
-
-
// copy addr
-
scan_addr = _scan_addr ;
-
-
for ( int i = 0 ; i < threadNum ; i++ )
-
{
-
pthread_t thread ;
-
pthreadList.push_back ( thread ) ;
-
}
-
}
-
-
-
int do_scan ( struct sockaddr_in dest_addr )
-
{
-
int ret , conn_fd = socket ( AF_INET , SOCK_STREAM , 0 ) ;
-
-
if ( conn_fd < 0 )
-
log_info ("socket" , __LINE__) ;
-
-
ret = connect ( conn_fd , (struct sockaddr *)&dest_addr ,
-
sizeof ( struct sockaddr_in )) ;
-
if ( ret < 0 )
-
{
-
if ( errno == ECONNREFUSED )
-
{
-
close (conn_fd ) ;
-
return -1; // target port refused service
-
}
-
else
-
{
-
close ( conn_fd ) ;
-
return -2; // other error type
-
}
-
-
}
-
else
-
{
-
-
printf ("port %d found in %s \n" , ntohs(dest_addr.sin_port) , inet_ntoa(dest_addr.sin_addr)) ;
-
close (conn_fd) ;
-
return 1 ;
-
}
-
return 0 ;
-
}
-
-
-
void* scanner ( void *arg )
-
{
-
unsigned short int i ;
-
scanSegment scan_segment ;
-
struct sockaddr_in dest_addr ;
-
-
memcpy ( &scan_segment , arg , sizeof ( scanSegment )) ;
-
-
dest_addr.sin_family = AF_INET ;
-
dest_addr.sin_addr = scan_segment.scan_addr ;
-
-
for ( i = scan_segment.from_port ; i != scan_segment.to_port ; i++ )
-
{
-
dest_addr.sin_port = htons ( i ) ;
-
-
printf ("detected by thread %lu , results :\n" , pthread_self() ) ;
-
-
switch ( do_scan ( dest_addr ) )
-
{
-
case -1 :
-
printf ("refused service\n" ,i ) ;
-
break ;
-
-
case -2 :
-
printf ("other type error \n" , i ) ;
-
break ;
-
-
case 1:
-
printf ("check port %d free " , i ) ;
-
break ;
-
default :
-
printf ("unknown error \n") ;
-
}
-
-
}
-
-
}
-
-
void Scanner::run ()
-
{
-
scanSegment segment ;
-
segment.scan_addr = scan_addr ;
-
-
-
for ( int i = 0 ; i < threadNum ; i++ )
-
{
-
segment.from_port = i*scan_len + 1 ;
-
-
if ( i == threadNum -1 )
-
{
-
segment.to_port = scan_max_port ;
-
}
-
else
-
{
-
segment.to_port = segment.from_port + scan_len -1 ;
-
}
-
-
if ( pthread_create ( &pthreadList[i] , NULL , scanner , (void *)&segment ) )
-
{
-
log_info ("pthread_create" , __LINE__) ;
-
}
-
-
pthread_join ( pthreadList[i] , NULL ) ;
-
}
-
}
// Main.cpp
-
// Main.cpp
-
-
#include <stdio.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <netinet/in.h>
-
#include <sys/socket.h>
-
#include <sys/types.h>
-
#include <arpa/inet.h>
-
-
#include "my_scanner.h"
-
-
using namespace std ;
-
-
void usage_info ( void )
-
{
-
printf ("method usage : \n") ;
-
printf ("[-m][max port ]\t [-a][server address \"xxx.xxx.xxx.xxx\"]\t [-n][-thread number] \n") ;
-
}
-
-
-
int main ( int argc , char *argv[] )
-
{
-
int i ;
-
int max_port ; // -m
-
int thread_num ; // -n
-
struct in_addr destAddr ; // -a
-
-
Scanner *myScanner ;
-
-
-
for ( i = 0 ; i < argc ; i++ )
-
{
-
if ( strcmp ( "-m" , argv[i] ) == 0 )
-
{
-
max_port = atoi (argv[i+1]) ;
-
if ( max_port < 0 || max_port > 65536 )
-
{
-
perror (" invalid port number ") ;
-
return -1 ;
-
}
-
}
-
-
if ( strcmp ( "-a" , argv[i] ) == 0 )
-
{
-
printf ("input ip address : %s \n", argv[i+1]) ;
-
-
if ( inet_aton (argv[i+1] , &destAddr ) < 0 )
-
{
-
perror (" invalid ip address ") ;
-
return -1 ;
-
}
-
}
-
-
if ( strcmp ( "-n" , argv[i] ) == 0 )
-
{
-
thread_num = atoi (argv[i+1]) ;
-
-
if ( thread_num <= 0 )
-
{
-
perror (" invalid threadnum ") ;
-
return -1 ;
-
}
-
}
-
}
-
-
printf ("here is the info you input\n") ;
-
printf ("max port : %d \n" , max_port ) ;
-
// printf ("address ip : %s\n", inet_nota (destAddr) ) ;
-
printf ("thread number : %d \n" , thread_num) ;
-
-
-
myScanner = new Scanner (thread_num , destAddr , max_port ) ;
-
myScanner->run () ;
-
-
-
goto success ;
-
-
error :
-
printf ("main error") ;
-
goto success ;
-
success:
-
return 0 ;
-
}
程序运行顺序:
1. 首先在一个 terminal 中运行 ./server
2. 然后在新开启一个 terminal 输入命令
-m (你要扫描检测的端口的最大值 [0,65535]) -a (你要检查端口所在的主机 IP 以 xxx.xxx.xxx.xxx 的格式) -n (你要开启多少个线程并行检查端口)
例如
-m 1027 -a 127.0.0.1 -n 100
end
阅读(1736) | 评论(0) | 转发(0) |