多线程扫描指定IP的端口,求助!

yangkunhenry 2009-06-19 01:12:55
先前写了一个单线程的扫描端口的程序,发现扫描端口太慢,
然后自己试着写多线程下的扫描程序,以前没写过多线程的程序,写成这样,
哪位大侠帮我改改错,给我点意见,谢谢了!!!

#include <iostream>
#include <Winsock2.h>
#include <string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

int i;
int PortEnd;
string IPstr;
CRITICAL_SECTION g_sect;
DWORD WINAPI ThreadProc1(LPVOID lpParam)
{
while(1)
{
EnterCriticalSection(&g_sect);//获得临界区对象所有权
Sleep(10);
if(i<=PortEnd)
{
Sleep(10);
SOCKET testsocket;
int iopenedport = 0;
struct sockaddr_in target_addr;

cout << "正在建立socket............." << endl;
if ((testsocket=socket (AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET)
{
cout << "Socket建立失败!" << endl;
exit(0);
}
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(i);
target_addr.sin_addr.s_addr = inet_addr (IPstr.c_str());
cout << "正在扫描端口:" << i << endl;
if (connect (testsocket, (struct sockaddr *) &target_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
cout << "端口" << i << "关闭!" << endl;
else
{
iopenedport++;
cout << "端口" << i << "开放\n" << endl;
}
i++;
LeaveCriticalSection(&g_sect);//释放临界区对象所有权
}
else
{
LeaveCriticalSection(&g_sect);//释放临界区对象所有权
break;
}
}
return 0;
}
DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
while(1)
{
EnterCriticalSection(&g_sect);//获得临界区对象所有权
Sleep(10);
if(i<=PortEnd)
{
Sleep(10);
SOCKET testsocket;
int iopenedport = 0;
struct sockaddr_in target_addr;

cout << "正在建立socket............." << endl;
if ((testsocket=socket (AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET)
{
cout << "Socket建立失败!" << endl;
exit(0);
}
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(i);
target_addr.sin_addr.s_addr = inet_addr (IPstr.c_str());
cout << "正在扫描端口:" << i << endl;
if (connect (testsocket, (struct sockaddr *) &target_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
cout << "端口" << i << "关闭!" << endl;
else
{
iopenedport++;
cout << "端口" << i << "开放\n" << endl;
}
i++;
LeaveCriticalSection(&g_sect);//释放临界区对象所有权
}
else
{
LeaveCriticalSection(&g_sect);//释放临界区对象所有权
break;
}
}
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1,1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
cerr<<"WSAStartup error!"<<err<<endl;
return 1;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 )
{

WSACleanup();
return 1;
}
int iportFrom,iportTo;
string str;
cout<<"Please input IP: ";
cin>>str;
cout<<"Please input 开始端口: ";
cin>>iportFrom;
cout<<"Please input 截止端口: ";
cin>>iportTo;

i=iportFrom;
PortEnd=iportTo;
IPstr=str;

DWORD IDThread1;
DWORD IDThread2;

HANDLE hthread1;
HANDLE hthread2;
hthread1=CreateThread(NULL,0,ThreadProc1,NULL,0,&IDThread1);
hthread2=CreateThread(NULL,0,ThreadProc2,NULL,0,&IDThread2);
CloseHandle(hthread1);
CloseHandle(hthread2);


cout<<IDThread1<<endl<<IDThread2<<endl;

InitializeCriticalSection(&g_sect); //初始化临界区对象


Sleep(10000);

DeleteCriticalSection(&g_sect); //释放临界区对象

return 0;
}

谢谢了!!!!!
...全文
189 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
red10057 2011-05-28
  • 打赏
  • 举报
回复
uuuuppp
a1419755245 2010-09-11
  • 打赏
  • 举报
回复
这个代码似曾相识啊

InitializeCriticalSection(&g_sect); //这个应该先初始化

hthread1=CreateThread(NULL,0,ThreadProc1,NULL,0,&IDThread1);
hthread2=CreateThread(NULL,0,ThreadProc2,NULL,0,&IDThread2);
CloseHandle(hthread1);
CloseHandle(hthread2);
a1419755245 2010-09-11
  • 打赏
  • 举报
回复
piaogupleshenmedongxidawodoafag
sound_of_silence 2009-06-24
  • 打赏
  • 举报
回复
class ConfigItem
{
public:
ConfigItem(){};
ConfigItem(string user, string pwd, string serv1, string port1, string serv2, string port2, string role);

string strUser;
string strPwd;
string strLoginServerIP;
string strLoginServerPort;
string strGameServerIP;
string strGameServerPort;
string strRole;
int iStatus;
int iFailedTimes;

CTime lastGameTime; //上一次发送保持游戏服务器连接指令的时间
CTime lastPartyTime; // 上一次发送保持频道服务器连接指令的时间
CTime lastMsgTime; // 上一次发送喊话指令的时间

unsigned int uCurrentMsgIndex;
};
static void GetServerList(string instruct, vector<STRU_GAME_SERVER>& servlist);

static void GetCharList(string instruct, vector<string>& charlist);

int DispatchID();
Conry 2009-06-22
  • 打赏
  • 举报
回复
sockinfo sf;
strcpy(sf.ip,str_ip);
for(int i=0;i<thread_sum;i++)
{
sf.port=port_from+i;
hthread[i]=CreateThread(NULL,0,ThreadProc,(LPVOID)&sf,0,&threadID);
}

你这里都是用的一个sf当然就是最后一个端口

几个线程就用几个sf

给你一个我写的改进版的


#include <stdlib.h>
#include <stdio.h>
#include <Winsock2.h>

#pragma comment(lib,"ws2_32.lib")

typedef struct PortInfo
{
char ip[32];
short fromPort;
short toPort;
short *openedPort;
short openedPortCount;
}PORTINFO,*PPORTINFO;


DWORD WINAPI ThreadProc(LPVOID lpParam)
{
PPORTINFO portinfo=(PPORTINFO)lpParam;

if(portinfo==NULL)
{
return -1;
}

short fromPort=portinfo->fromPort;
short toPort=portinfo->toPort;

while(fromPort<=toPort)
{
SOCKET testsocket;
struct sockaddr_in target_addr;

printf("正在建立socket.............\n");
if ((testsocket=socket (AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET)
{
printf("Socket建立失败!\n");
return 0;
}

target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(fromPort);
target_addr.sin_addr.s_addr = inet_addr (portinfo->ip);

printf("正在扫描端口 %s:%u \n",portinfo->ip,fromPort);

if (connect (testsocket, (struct sockaddr *) &target_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
printf("端口 %u 关闭!\n",fromPort);
}
else
{
portinfo->openedPort[portinfo->openedPortCount]=fromPort;
portinfo->openedPortCount++;
printf("端口 %u 开放!\n",fromPort);
}

closesocket(testsocket);

fromPort++;

//Sleep(20);
}

return 0;
}

#define THREAD_COUNT 100

int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2,2 );

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 )
{
printf("WSAStartup error!\n");
return 1;
}

if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{

WSACleanup();
return 1;
}

short iportFrom,iportTo;
char IPstr[32];

memset(IPstr,0,sizeof(IPstr));

printf("Please input IP:\n");
scanf("%16s",IPstr);

printf("Please input 开始端口:");
scanf("%hd",&iportFrom);

printf("Please input 截止端口:");
scanf("%hd",&iportTo);

if(iportTo<iportFrom||iportFrom<=0||iportTo<=0)
{
printf("端口号要大于0,并且截止端口要大于或者等于开始端口!\n");
return -1;
}

int threadCount=THREAD_COUNT;

int tmp=(iportTo-iportFrom)/THREAD_COUNT;
if(tmp==0)
{
tmp=1;
threadCount=iportTo-iportFrom+1;
}

//int resver=(iportTo-iportFrom)%5;
PPORTINFO portinfo= new PORTINFO[threadCount];

//PORTINFO portinfo[THREAD_COUNT];
HANDLE* hthread=new HANDLE[threadCount];
DWORD IDThread;

DWORD beginTime=GetTickCount();

for(int i=0;i<threadCount-1;i++)
{
strcpy(portinfo[i].ip,IPstr);
portinfo[i].fromPort=iportFrom+i*tmp;
portinfo[i].toPort=portinfo[i].fromPort+tmp-1;
portinfo[i].openedPortCount=0;
portinfo[i].openedPort = new short[tmp];

hthread[i]=CreateThread(NULL,0,ThreadProc,&portinfo[i],0,&IDThread);
}

strcpy(portinfo[threadCount-1].ip,IPstr);
portinfo[threadCount-1].fromPort=iportFrom+(threadCount-1)*tmp;
portinfo[threadCount-1].toPort=iportTo;
portinfo[threadCount-1].openedPortCount=0;
portinfo[threadCount-1].openedPort = new short[iportTo-portinfo[threadCount-1].fromPort+1];

hthread[threadCount-1]=CreateThread(NULL,0,ThreadProc,&portinfo[threadCount-1],0,&IDThread);

for(int i=0;i<threadCount;i++)
{
WaitForSingleObject(hthread[i],INFINITE);
}

for(int i=0;i<threadCount;i++)
{
CloseHandle(hthread[i]);

}

DWORD endTime=GetTickCount();

printf("开始时间:%d\n结束时间:%d\n花费时间:%d\n",beginTime,endTime,endTime-beginTime);

for(int i=0;i<threadCount;i++)
{
for(int j=0;j<portinfo[i].openedPortCount;j++)
{
printf("IP:%s 开放的端口:%hd\n",portinfo[i].ip,portinfo[i].openedPort[j]);
}
}

for(int i=0;i<threadCount;i++)
{
delete[] portinfo[i].openedPort;
}

delete[] portinfo;
delete[] hthread;

return 0;
}
yangkunhenry 2009-06-20
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 Conry 的回复:]
WaitForMultipleObjects最多只能等待64个句柄,多了就出问题了,
而且你也用不着1个端口对应一个线程,一般一两百个线程就行了

WaitForMultipleObjects(thread_sum,hthread,FALSE,INFINITE);
可以改为,目的就是等待所有线程退出
for(int i=0;i <thread_sum;i++)
{
WaitForSingleObject(hthread[i],INFINITE);
}
[/Quote]
改了之后,显示只扫描了最后一个端口,这是什么原因?
yangkunhenry 2009-06-20
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <Winsock2.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")

typedef struct sock_information
{
char ip[17];
int port;
}sockinfo;

DWORD WINAPI ThreadProc(LPVOID laParam)
{
sockinfo sf=*(sockinfo*)laParam;

SOCKET sockcon=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockcon==INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
return 1;
}

sockaddr_in sacon;
sacon.sin_addr.S_un.S_addr=inet_addr(sf.ip);
sacon.sin_family=AF_INET;
sacon.sin_port=htons(sf.port);

if(connect(sockcon,(sockaddr*)&sacon,sizeof(sockaddr)==SOCKET_ERROR))
{
printf("Port %4d is closed!\n",sf.port);
}
else
{
printf("Port %4d is open!\n",sf.port);
}
closesocket(sockcon);

return 0;
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
return 1;
if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup();
return 1;
}
char str_ip[17];
memset(str_ip,0,17);
printf("Please input the IP:");
scanf("%s",str_ip);
fflush(stdin);

int port_from;
printf("Please input the port_from:");
scanf("%d",&port_from);
fflush(stdin);

int port_to;
printf("Please input the port_to:");
scanf("%d",&port_to);

int thread_sum=port_to-port_from+1; //得到要扫描的端口数目
HANDLE* hthread=new HANDLE[thread_sum];
DWORD threadID;

sockinfo sf;
strcpy(sf.ip,str_ip);
for(int i=0;i<thread_sum;i++)
{
sf.port=port_from+i;
hthread[i]=CreateThread(NULL,0,ThreadProc,(LPVOID)&sf,0,&threadID);
}
for(int i=0;i<thread_sum;i++)
{
::WaitForSingleObject(hthread[i],INFINITE);
}
//::WaitForMultipleObjects(thread_sum,hthread,FALSE,INFINITE);
for(int i=0;i<thread_sum;i++)
{
CloseHandle(hthread[i]);
}
delete []hthread;
WSACleanup();
return 0;
}

改了还是有错,程序最后只扫描了最后一个端口,为什么啊,找不出错,帮帮忙吧大家!
Conry 2009-06-19
  • 打赏
  • 举报
回复
WaitForMultipleObjects最多只能等待64个句柄,多了就出问题了,
而且你也用不着1个端口对应一个线程,一般一两百个线程就行了

WaitForMultipleObjects(thread_sum,hthread,FALSE,INFINITE);
可以改为,目的就是等待所有线程退出
for(int i=0;i<thread_sum;i++)
{
WaitForSingleObject(hthread[i],INFINITE);
}
yangkunhenry 2009-06-19
  • 打赏
  • 举报
回复
谢谢我笨善良啦!
刚又写了一个,但运行的时候只是出现最后一个端口的结果,找了半天找不着错误

#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")

typedef struct sock_information
{
char ip[17];
int port;
}sockinfo;

DWORD WINAPI ThreadProc(LPVOID laParam)
{
sockinfo sf=*(sockinfo*)laParam;

SOCKET sockcon=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sockcon==INVALID_SOCKET)
{
printf("Error at socket(): %ld\n", WSAGetLastError());
return 1;
}

sockaddr_in sacon;
sacon.sin_addr.S_un.S_addr=inet_addr(sf.ip);
sacon.sin_family=AF_INET;
sacon.sin_port=htons(sf.port);

if(connect(sockcon,(sockaddr*)&sacon,sizeof(sockaddr)==SOCKET_ERROR))
{
printf("Port %4d is closed!\n",sf.port);
}
else
{
printf("Port %4d is open!\n",sf.port);
}
closesocket(sockcon);

return 0;
}
int main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
return 1;
if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup();
return 1;
}
char str_ip[17];
memset(str_ip,0,17);
printf("Please input the IP:");
scanf("%s",str_ip);
fflush(stdin);

int port_from;
printf("Please input the port_from:");
scanf("%d",&port_from);
fflush(stdin);

int port_to;
printf("Please input the port_to:");
scanf("%d",&port_to);

int thread_sum=port_to-port_from+1; //得到要扫描的端口数目
HANDLE* hthread=new HANDLE[thread_sum];
DWORD threadID;

sockinfo sf;
strcpy(sf.ip,str_ip);
for(int i=0;i<thread_sum;i++)
{
sf.port=port_from+i;
hthread[i]=CreateThread(NULL,0,ThreadProc,(LPVOID)&sf,0,&threadID);
}
::WaitForMultipleObjects(thread_sum,hthread,FALSE,INFINITE);
for(int i=0;i<thread_sum;i++)
{
CloseHandle(hthread[i]);
}
delete []hthread;
WSACleanup();
return 0;
}
Conry 2009-06-19
  • 打赏
  • 举报
回复
给你一个代码,在你的基础上改的


#include <stdlib.h>
#include <stdio.h>
#include <Winsock2.h>

#pragma comment(lib,"ws2_32.lib")

typedef struct PortInfo
{
char ip[32];
short fromPort;
short toPort;
}PORTINFO,*PPORTINFO;


DWORD WINAPI ThreadProc(LPVOID lpParam)
{
PPORTINFO portinfo=(PPORTINFO)lpParam;

if(portinfo==NULL)
{
return -1;
}

short fromPort=portinfo->fromPort;
short toPort=portinfo->toPort;

while(fromPort<=toPort)
{
SOCKET testsocket;
struct sockaddr_in target_addr;

printf("正在建立socket.............\n");
if ((testsocket=socket (AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET)
{
printf("Socket建立失败!\n");
return 0;
}

target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(fromPort);
target_addr.sin_addr.s_addr = inet_addr (portinfo->ip);

printf("正在扫描端口 %s:%u \n",portinfo->ip,fromPort);

if (connect (testsocket, (struct sockaddr *) &target_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
printf("端口 %u 关闭!\n",fromPort);
}
else
{
printf("端口 %u 开放!\n",fromPort);
}

fromPort++;

Sleep(20);
}

return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2,2 );

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 )
{
printf("WSAStartup error!\n");
return 1;
}

if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{

WSACleanup();
return 1;
}

short iportFrom,iportTo;
char IPstr[32];

memset(IPstr,0,sizeof(IPstr));

printf("Please input IP:\n");
scanf("%16s",IPstr);

printf("Please input 开始端口:");
scanf("%hd",&iportFrom);

printf("Please input 截止端口:");
scanf("%hd",&iportTo);

if(iportTo<iportFrom||iportTo<=0)
{
printf("端口号要大于0,并且截止端口要大于或者等于开始端口!\n");
return -1;
}

int tmp=(iportTo-iportFrom)/2;

PORTINFO portinfo1,portinfo2;

strcpy(portinfo1.ip,IPstr);
portinfo1.fromPort=iportFrom;
portinfo1.toPort=iportFrom+tmp;

strcpy(portinfo2.ip,IPstr);
portinfo2.fromPort=portinfo1.toPort+1;
portinfo2.toPort=iportTo;

DWORD IDThread1;
DWORD IDThread2;

HANDLE hthread[2];

hthread[0]=CreateThread(NULL,0,ThreadProc,&portinfo1,0,&IDThread1);
hthread[1]=CreateThread(NULL,0,ThreadProc,&portinfo2,0,&IDThread2);

WaitForMultipleObjects(2,hthread,TRUE,INFINITE);

CloseHandle(hthread[0]);
CloseHandle(hthread[1]);

return 0;
}



yangkunhenry 2009-06-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 Ryanwen 的回复:]
ThreadProc一个就够了,都是一样的代码,写这么多干吗
[/Quote]
刚学,不会搞,大哥帮忙优化一下把代码贴出来让小弟看看?
谢谢了!!!
Conry 2009-06-19
  • 打赏
  • 举报
回复
1 为什么要用两个线程函数?
一个就够了,调用2次就行了,你想调用几次就几次
2 你这种方法也不好,还要同步,
应该这样做比较好,得到起止端口号后,把它按你要创建的线程个数平均分配
比如线程1扫描 1-1000,线程2 扫描1001-2000,这个数可以作为线程参数传给线程
线程函数取得自己的起止端口开始扫描就行了,不存在同步的问题了
Ryanwen 2009-06-19
  • 打赏
  • 举报
回复
ThreadProc一个就够了,都是一样的代码,写这么多干吗
bragi523 2009-06-19
  • 打赏
  • 举报
回复
sleep为什么也放临界区里面?
Ryanwen 2009-06-19
  • 打赏
  • 举报
回复
这个代码似曾相识啊

InitializeCriticalSection(&g_sect); //这个应该先初始化

hthread1=CreateThread(NULL,0,ThreadProc1,NULL,0,&IDThread1);
hthread2=CreateThread(NULL,0,ThreadProc2,NULL,0,&IDThread2);
CloseHandle(hthread1);
CloseHandle(hthread2);

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧