#include <iostream>
#include <winsock.h>
#pragma comment(lib,"wsock32.lib")
#define DEF_BUF_SIZE 1024
#define ICMP_HEADER_SIZE 12
typedef struct _ICMP_HEADER
{
BYTE bType;
USHORT nCheckSum;
}ICMP_HEADER, *PICMP_HEADER;
USHORT GetCheckSum(LPBYTE lpBuff, DWORD dwSize)
{
DWORD dwCheckSum = 0;
USHORT* lpWord = (USHORT*)lpBuff;
while(dwSize > 1)
{
dwCheckSum += *lpWord++;
dwSize -= 2;
}
if(dwSize ==1)
dwCheckSum += *((LPBYTE)lpBuff);
return (USHORT)(~dwCheckSum);
}
DWORD WINAPI Thread(LPVOID lpParmeter);
HANDLE g_hMutex;
int main()
{
static int u=2,i=0;
HANDLE* hThread = new HANDLE[u];
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD( 1, 1 );
WSAStartup( wVersionRequested, &wsaData );
for(;i<u; i++)
{
g_hMutex=CreateMutex(NULL,FALSE,"MutexToRecive");
hThread[i]=CreateThread(NULL,0,Thread,&i,0,NULL);
Sleep(50);
}
SetEvent(g_hMutex);
WaitForMultipleObjects(i, hThread, TRUE, INFINITE);
for (; i<u; i++)
CloseHandle(hThread[i]);
return 0;
}
DWORD WINAPI Thread(LPVOID lpParmeter)
{ int x=3389,nRet;
int idx = *(int*)lpParmeter;
SOCKET s = socket(AF_INET,SOCK_RAW, IPPROTO_ICMP);
if(s == INVALID_SOCKET)
{
printf("SOCKET error Code for the %s\n",s);
return 0;
}
struct sockaddr_in addr;
addr.sin_family =AF_INET;
addr.sin_port = htons(x);
static unsigned long iSIP = inet_addr("192.168.1.1");
static unsigned long iEIP = inet_addr("192.168.1.26");
static unsigned long s1 = ntohl(iSIP);
static unsigned long e1 = ntohl(iEIP);
for(;s1 <= e1;s1++)
{
WaitForSingleObject(g_hMutex, INFINITE);
if (s1 <= e1)
{
Sleep(3);
addr.sin_addr.S_un.S_addr = ntohl(s1);//获取每次For循环后的IP
char ICMPPack[ICMP_HEADER_SIZE] = {0};
PICMP_HEADER pICMPHeader = (PICMP_HEADER)ICMPPack;
pICMPHeader->bType = 8;//定义8位字节的数据包
int nTime = 1000; //设置超时时间
int ret = ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTime, sizeof(nTime));//发送的数据包到目标IP,超时就结束发送
char szRcvBuff[DEF_BUF_SIZE];
SOCKADDR_IN SourceSockAddr;
pICMPHeader->nCheckSum = GetCheckSum((LPBYTE)(ICMPPack), ICMP_HEADER_SIZE);
sendto(s, ICMPPack, ICMP_HEADER_SIZE, 0, (SOCKADDR*)&addr, sizeof(addr));//将指定字节数的数据发送到指定的终结点
int nLen = sizeof(SOCKADDR_IN);
nRet = ::recvfrom(s, szRcvBuff,DEF_BUF_SIZE,0,(SOCKADDR*)&SourceSockAddr,&nLen);//接收目标IP的数据
if(nRet != SOCKET_ERROR)
{
SOCKET c=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//建立一个SOCKET
if (c==INVALID_SOCKET)//SOCKET返回值为INVALID_SOCKET错误退出连接
{
return -1;
}
DWORD dwset=1;
int ret=ioctlsocket(c,FIONBIO,(LPDWORD)&dwset); //用非阻塞的连接
if (ret==SOCKET_ERROR)//设置ioctlsocket返回值为SOCKET_ERROR 退出
{
return -1;
}
DWORD start=GetTickCount();
connect(c,(SOCKADDR*)&addr,sizeof addr);//创建一个计算机之间的通信
timeval timeout;
fd_set r;
FD_ZERO(&r);//总是这样先清空一个描述符集
FD_SET(c,&r); //把c放入要测试的描述符集
timeout.tv_sec=1;//设置秒
timeout.tv_usec=0;//设置微秒
ret=select(0,0,&r,0,&timeout);
if (ret<=0) //超时或SOCKET_ERROR
{printf("%s %d Close \n",inet_ntoa(addr.sin_addr),x);}
else
{printf("%s %d Open \n",inet_ntoa(addr.sin_addr),x);}
dwset=0;
ret=ioctlsocket(c,FIONBIO,(LPDWORD)&dwset);
if (ret==SOCKET_ERROR)
{
printf("error %d\n",WSAGetLastError());
}
}
else {printf("%s Not online\n",inet_ntoa(addr.sin_addr));}
}
else
{
ReleaseMutex(g_hMutex);
break;
}
}
return 0;
}
10 个解决方案
#1
做同一件事情,多线程可能比单线程更慢,因为中间多了线程切换的开销.
当然,如果多个CPU同时去跑可能会更快.
当然,如果多个CPU同时去跑可能会更快.
#2
多线程的话,你可以分段扫描:
比如:第一个线程扫描192.168.1.1~192.168.1.50
第二个扫描:192.168.1.50~192.168.1.100
。。。。
另外,设置的超时可以短一点,你那1000太长了吧
比如:第一个线程扫描192.168.1.1~192.168.1.50
第二个扫描:192.168.1.50~192.168.1.100
。。。。
另外,设置的超时可以短一点,你那1000太长了吧
#3
另外,如果是分段扫描,那么就可以不考虑线程同步
相比使用内核对象进行同步,速度快多了
#4
谢谢3楼的朋友我刚刚删除了WaitForSingleObject(g_hMutex, INFINITE);
程序设置为60 超时设置为500 速度快了很多 但是开头都是192.168.1.1 这样的 为什么会这样? 高手能帮我修改一下吗
#5
朋友请问 要怎么修改? 我听agoago_2009修改后速度有些改善了
WaitForSingleObject(g_hMutex, INFINITE);
这段删除后速度就更快 但是 出现了很多192.168.1.1 5个线程就出现了5个192.168.1.1
加着一段后WaitForSingleObject(g_hMutex, INFINITE);
就避免了这样 要怎么修改才能提升速度很扫描正确
#6
在CreateThread的时候,由 lpParameter传入参数i(for 循环创建线程时的i)
线程个数有n个,线程中有一个计数count的话:
第一段:n*count1 + i
第二段:n*count2 + i (i已经++)
。。。。。
这样就分段了,因为他们取模的话,模值是0~n-1
#7
没有仔细看老兄的代码.
这里有点一般性的建议:
要优化代码,首先要确定耗时最长一个或多个点,用Profile类或者工具来测试时间,以确定热点.
之后对耗时最长的部分做改进.如果如此之后还是不能达到要求,有2种可能性:
1. 程序要做的事在现有的环境下至少都要消耗这么多的时间(时间下限);
2. 程序结构有问题,在现有结构再怎么优化都不可能达到要求,这样就要重新设计程序的代码结构.
即使就这样140行代码也可能有这样的问题.
另外,对于使用同步对象,请仔细挑选,通常是优先使用用户级的同步对象,在必须的时候才使用内核
同步对象,原因在于内核对象的使用需要在内核空间运行,这样就有了从用户态切换到内核态,然后由
内核态返回到用户态的开销.
当然,我这里只是建议,这些动作不一定有效,毕竟我没有仔细的看代码.
#8
仅供参考
#include <windows.h>
#include <stdio.h>
char cmdstr[256];
int i;
int YN(int k) {
FILE *f;
char fn[40];
char ln[80];
int yn=0;
sprintf(fn,"d:\\ping%d.txt",k);
f=fopen(fn,"r");
if (NULL!=f) {
fgets(ln,80,f);
fgets(ln,80,f);
fgets(ln,80,f);
if (1==fscanf(f,"Re%c",&yn)) yn='q'-yn;
fclose(f);
unlink(fn);
}
return yn;
}
void main() {
for (i=115;i<130;i++) {
sprintf(cmdstr,"cmd /c ping 192.168.2.%d -n 1 -w 1000 >d:\\ping%d.txt",i,i);
WinExec(cmdstr,SW_HIDE);
}
Sleep(3000);
for (i=115;i<130;i++) {
printf("%d 192.168.2.%d\n",YN(i),i);
}
}
//1 192.168.2.115
//0 192.168.2.116
//0 192.168.2.117
//0 192.168.2.118
//1 192.168.2.119
//0 192.168.2.120
//0 192.168.2.121
//0 192.168.2.122
//1 192.168.2.123
//0 192.168.2.124
//0 192.168.2.125
//1 192.168.2.126
//0 192.168.2.127
//1 192.168.2.128
//0 192.168.2.129
#9
我是新手学多线程不久 很多都不懂 你说的我也不是很明白
你能修改一下代码吗 谢谢朋友了
#10
不懂。。。
#1
做同一件事情,多线程可能比单线程更慢,因为中间多了线程切换的开销.
当然,如果多个CPU同时去跑可能会更快.
当然,如果多个CPU同时去跑可能会更快.
#2
多线程的话,你可以分段扫描:
比如:第一个线程扫描192.168.1.1~192.168.1.50
第二个扫描:192.168.1.50~192.168.1.100
。。。。
另外,设置的超时可以短一点,你那1000太长了吧
比如:第一个线程扫描192.168.1.1~192.168.1.50
第二个扫描:192.168.1.50~192.168.1.100
。。。。
另外,设置的超时可以短一点,你那1000太长了吧
#3
另外,如果是分段扫描,那么就可以不考虑线程同步
相比使用内核对象进行同步,速度快多了
#4
谢谢3楼的朋友我刚刚删除了WaitForSingleObject(g_hMutex, INFINITE);
程序设置为60 超时设置为500 速度快了很多 但是开头都是192.168.1.1 这样的 为什么会这样? 高手能帮我修改一下吗
#5
朋友请问 要怎么修改? 我听agoago_2009修改后速度有些改善了
WaitForSingleObject(g_hMutex, INFINITE);
这段删除后速度就更快 但是 出现了很多192.168.1.1 5个线程就出现了5个192.168.1.1
加着一段后WaitForSingleObject(g_hMutex, INFINITE);
就避免了这样 要怎么修改才能提升速度很扫描正确
#6
在CreateThread的时候,由 lpParameter传入参数i(for 循环创建线程时的i)
线程个数有n个,线程中有一个计数count的话:
第一段:n*count1 + i
第二段:n*count2 + i (i已经++)
。。。。。
这样就分段了,因为他们取模的话,模值是0~n-1
#7
没有仔细看老兄的代码.
这里有点一般性的建议:
要优化代码,首先要确定耗时最长一个或多个点,用Profile类或者工具来测试时间,以确定热点.
之后对耗时最长的部分做改进.如果如此之后还是不能达到要求,有2种可能性:
1. 程序要做的事在现有的环境下至少都要消耗这么多的时间(时间下限);
2. 程序结构有问题,在现有结构再怎么优化都不可能达到要求,这样就要重新设计程序的代码结构.
即使就这样140行代码也可能有这样的问题.
另外,对于使用同步对象,请仔细挑选,通常是优先使用用户级的同步对象,在必须的时候才使用内核
同步对象,原因在于内核对象的使用需要在内核空间运行,这样就有了从用户态切换到内核态,然后由
内核态返回到用户态的开销.
当然,我这里只是建议,这些动作不一定有效,毕竟我没有仔细的看代码.
#8
仅供参考
#include <windows.h>
#include <stdio.h>
char cmdstr[256];
int i;
int YN(int k) {
FILE *f;
char fn[40];
char ln[80];
int yn=0;
sprintf(fn,"d:\\ping%d.txt",k);
f=fopen(fn,"r");
if (NULL!=f) {
fgets(ln,80,f);
fgets(ln,80,f);
fgets(ln,80,f);
if (1==fscanf(f,"Re%c",&yn)) yn='q'-yn;
fclose(f);
unlink(fn);
}
return yn;
}
void main() {
for (i=115;i<130;i++) {
sprintf(cmdstr,"cmd /c ping 192.168.2.%d -n 1 -w 1000 >d:\\ping%d.txt",i,i);
WinExec(cmdstr,SW_HIDE);
}
Sleep(3000);
for (i=115;i<130;i++) {
printf("%d 192.168.2.%d\n",YN(i),i);
}
}
//1 192.168.2.115
//0 192.168.2.116
//0 192.168.2.117
//0 192.168.2.118
//1 192.168.2.119
//0 192.168.2.120
//0 192.168.2.121
//0 192.168.2.122
//1 192.168.2.123
//0 192.168.2.124
//0 192.168.2.125
//1 192.168.2.126
//0 192.168.2.127
//1 192.168.2.128
//0 192.168.2.129
#9
我是新手学多线程不久 很多都不懂 你说的我也不是很明白
你能修改一下代码吗 谢谢朋友了
#10
不懂。。。