我在linux下写了个简单的多线程端口扫描程序,运行时出现问题,请教一下!
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in.h>
struct sockaddr_in servaddr;
int g_nThreadNum, g_nMaxThread;
long g_nNowPort;
char *host;
struct timeval timeout;
static void* thread_scan_port(void *pPort)
{
int sockfd, flags, error,nPort, retconn, retval, len;
fd_set wfds;
pthread_detach(pthread_self());
nPort = *(int *)pPort;
//printf( "nPort = %d\n ", nPort);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror( "\nsocket ");
g_nThreadNum--;
return(NULL);
}
/* 设为非阻塞方式 */
if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0)
{
perror( "\nfcntl: ");
g_nThreadNum--;
return(NULL);
}
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror( "\nfcntl: ");
g_nThreadNum--;
return(NULL);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(nPort);
servaddr.sin_addr.s_addr = inet_addr(host);
if ((retconn = connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0)
if (EINPROGRESS != errno)
{
g_nThreadNum--;
return(NULL);
}
FD_ZERO(&wfds);
FD_SET(sockfd, &wfds);
retval = select(sockfd+1, NULL, &wfds, NULL, &timeout);
if (0 == retval || -1 == retval)/* 超时或者select错误 */
{
//printf( "port connect is fail!\n ");
close(sockfd);
g_nThreadNum--;
return(NULL);
}
if (FD_ISSET(sockfd, &wfds))/* sockfd可写 */
{
len = sizeof(error);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
{
g_nThreadNum--;
return(NULL);
}
}
else
{
perror( "\nFD_ISSET: ");
g_nThreadNum--;
return(NULL);
}
if (error) /* 链接时有错误发生 */
{
close(sockfd);
g_nThreadNum--;
return(NULL);
}
else/* 链接成功返回0 */
{
printf( "port %d is opened!\n ", nPort);
g_nThreadNum--;
return(NULL);
}
}
/* 等待所有线程结束 */
void WaitThreadEnd(void)
{
usleep(1000);
printf( "\nThread ending....\n ");
while(g_nThreadNum> 0)
{
usleep(1);
printf( " =|=\t%d threads \r ",g_nThreadNum);
}
printf( "threadnum = %d ", g_nThreadNum);
printf( "\nThread ended!\n ");
}
int main(int argc, char **argv)
{
int i, j, nStartPort, nEndPort,nThread, ret, index;
int nPort[1000];
pthread_t tid;
/* 当前的线程数量 */
g_nThreadNum = 0;
host = argv[1];
nThread = atoi(argv[3]);
sscanf(argv[2], "%d-%d ", &nStartPort, &nEndPort);
printf( "nStartPort = %d\n ", nStartPort);
printf( "nEndPort = %d\n ", nEndPort);
/* 最大线程数 */
g_nMaxThread = (nThread > = 1000)? 1000 : nThread;
timeout.tv_usec = 0;
if (g_nMaxThread > 500)
timeout.tv_sec = 2;
else
timeout.tv_sec = 1;
printf( "MaxThread = %d\n ", g_nMaxThread);
printf( "ThreadNum = %d\n ", g_nThreadNum);
index = 0;
for (i = nStartPort; i <= nEndPort; i++, index++)
nPort[index] = i;
for (j = 0; j < index; j++)
{
g_nThreadNum++;
/* 若超过最大的线程数,程序休眠等待线程的释放 */
while (g_nThreadNum > = g_nMaxThread)
{
usleep(10);
}
ret = pthread_create(&tid, NULL, (void *)thread_scan_port, &nPort[j]);
if (0 != ret)
{
perror( "\npthread_create ");
exit(1);
}
}
//printf( "ThreadNum = %d\n ", g_nThreadNum);
WaitThreadEnd();
return 0;
}
编译: gcc -lpthread PortScanner.c -o PortScanner
运行:./PortScanner 192.168.2.1 1-1000 500
注:192.168.2.1 要扫描的地址 1-1000 端口范围 500 指定可以产生的最大线程数
当端口和线程比较大时运行就出问题了
[解决办法]
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <pthread.h>
#include <thread_db.h>
#include <arpa/inet.h>
#define MAX_PORT 4000
#define MAX_THREAD 100
/* basename(argv[0]). netBSD,linux and gnu libc all define it. */
extern char *__progname;
/* globals */
int port_num,thread_num=100;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(int argc,char **argv)
{
void *thread_main(void *);
pthread_t tid;
#ifndef HAVE__PROGNAME
__progname = argv[0];
#endif
printf( "----kf_701 scan tool--------- ");
if(argc != 2){
fprintf(stderr, "* Usage: %s host ",__progname);
exit(0);
}
/* create threads */
int i;
for(i=0;i <MAX_THREAD;i++)
pthread_create(&tid,NULL,&thread_main,argv[1]);
/* main pause */
for( ; ; )
pause();
}
void *thread_main(void *arg)
{
struct sockaddr_in sa;
struct hostent *host;
int i,sockfd;
pthread_detach(pthread_self());
/* init sockaddr_in struct */
bzero(&sa,sizeof(struct sockaddr));
sa.sin_family = AF_INET;
if(inet_aton((char *)arg,&sa.sin_addr) == 0){
host = gethostbyname((char *)arg);
if(host == NULL){
fprintf(stderr, "Hostname Error: %s ",hstrerror(h_errno));
exit(1);
}
sa.sin_addr = *(struct in_addr *)(host-> h_addr_list[0]);
}
while(1){
/* get a port number */
if(pthread_mutex_lock(&mutex) != 0) exit(1);
if(++port_num > MAX_PORT){
if(pthread_mutex_unlock(&mutex) != 0) exit(1);
if(--thread_num == 0){
printf( "----------------------------- ");
exit(0);
}
pthread_exit(NULL);
}
i=port_num;
if(pthread_mutex_unlock(&mutex) != 0) exit(1);
/* try to connect */
sa.sin_port=htons(i);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
perror( "Create socket error "),exit(1);
if(connect(sockfd,(struct sockaddr *)&sa,sizeof(sa)) == 0)
printf( "* port %d is open ",i);
if(close(sockfd) < 0)
perror( "shutdown error "),exit(1);
}/*end while*/
}