www.pudn.com > linuxsocket.rar > my_scaner.c
// 端口扫描程序,只支持扫描TCP端口 #include#include #include #include #include #include #include #include #include #include // 定义一个端口区间信息 typedef struct _port_segment { struct in_addr dest_ip; // 目标IP unsigned short int min_port; // 起始端口 unsigned short int max_port; // 最大端口 } port_segment; /*自定义的错误处理函数*/ void my_err(const char * err_string, int line) { fprintf(stderr, "line:%d ", line); perror(err_string); exit(1); } /* * 描 述:扫描某一IP地址上的某一个端口的函数 * 返回值: -1 出错 * 0 目标端口未打开 * 1 目标端口已打开 */ int do_scan(struct sockaddr_in serv_addr) { int conn_fd; int ret; // 创建一个TCP套接字 conn_fd = socket(AF_INET, SOCK_STREAM,0); if (conn_fd < 0) { my_err("socket", __LINE__); } // 向服务器端发送连接请求 if ( (ret = connect(conn_fd, (struct sockaddr *)&serv_addr, sizeof (struct sockaddr))) < 0 ) { if (errno == ECONNREFUSED) { // 目标端口未打开 close(conn_fd); return 0; } else { // 其他错误 close(conn_fd); return -1; } } else if (ret == 0){ printf("port %d found in %s\n", ntohs(serv_addr.sin_port), inet_ntoa(serv_addr.sin_addr)); close(conn_fd); return 1; } return -1; // 实际执行不到这里,只是为了消除编译程序时产生的警告 } // 执行扫描的线程,扫描某一区间的端口 void * scaner(void *arg) { unsigned short int i; struct sockaddr_in serv_addr; port_segment portinfo; // 端口信息 // 读取端口区间信息 memcpy(&portinfo, arg, sizeof(struct _port_segment)); // 初始化服务器端地址结构 memset(&serv_addr, 0, sizeof (struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = portinfo.dest_ip.s_addr; for (i=portinfo.min_port; i<=portinfo.max_port; i++) { serv_addr.sin_port = htons(i); if (do_scan(serv_addr) < 0) { continue; // 出错则退出进程 } } return NULL; } /* * 命令行参数:-m 最大端口, -a 目标主机的IP地址, -n 最大线程数 */ int main(int argc, char **argv) { pthread_t* thread; // 指向所有的线程ID int max_port; // 最大端口号 int thread_num; // 最大线程数 int seg_len; // 端口区间长度 struct in_addr dest_ip; // 目标主机IP int i; // 检查参数个数 if (argc != 7) { printf("Usage: [-m] [max_port] [-a] [serv_address] [-n] [thread_number]\n"); exit(1); } // 解析命令行参数 for (i=1; i 65535) { printf("Usage:invalid max dest port\n"); exit(1); } continue; } if (strcmp("-a", argv[i]) == 0) { if (inet_aton(argv[i+1], &dest_ip) == 0) { printf("Usage:invalid dest ip address\n"); exit(1); } continue; } if (strcmp("-n", argv[i]) == 0) { thread_num = atoi(argv[i+1]); if (thread_num <= 0) { printf("Usage:invalid thread_number\n"); exit(1); } continue; } } // 如果输入的最大端口号小于线程数,则将线程数设为最大端口号 if (max_port < thread_num) { thread_num = max_port; } seg_len = max_port / thread_num; if ( (max_port%thread_num) != 0 ) { thread_num += 1; } // 分配存储所有线程ID的内存空间 thread = (pthread_t*)malloc(thread_num*sizeof(pthread_t)); // 创建线程,根据最大端口号和线程数分配每个线程扫描的端口区间 for (i=0; i