#include "scanhost.h"
WSADATA wsadata;
SOCKET sockraw;
struct sockaddr_in dest,from,end;
int fromlen=sizeof(from);
char * recvbuf=new char[MAX_PING_PACKET_SIZE];
unsigned int addr=0;
long threadnumcounter=0,threadnumlimit=20;//进程
long *aa=&threadnumcounter;
void main(int argc,char *argv[]){
if(argc!=3){
cout<<"输入格式错误:scanhost start_ip end_ip"<<endl;
return;
}
if(WSAStartup(MAKEWORD(2,1),&wsadata)!=0){ //回送请求类型号不为0
cout<<"WSAStartup failed:"<<GetLastError()<<endl;
ExitProcess(STATUS_FAILED);
}
//创建原始套接字
sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
if(sockraw==INVALID_SOCKET){
cout<<"WSASocket() failed:"<<WSAGetLastError()<<endl;
ExitProcess(STATUS_FAILED);
}
//设置读取延时
int timeout=1000; //超时时间设置为1000ms。
int bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
if(bread==SOCKET_ERROR){
cout<<"fail to set recv timeout:"<<WSAGetLastError()<<endl;
ExitProcess(STATUS_FAILED);
}
//timeout=1000;
// bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
// if(bread==SOCKET_ERROR){
// cout<<"failed to set send timeout:"<<WSAGetLastError()<<endl;
// ExitProcess(STATUS_FAILED);
// }
memset(&dest,0,sizeof(dest));//将数据报清空初始化
unsigned long startip,endip;
dest.sin_family=AF_INET;
dest.sin_addr.s_addr=inet_addr(argv[1]);
startip=inet_addr(argv[1]);
end.sin_family=AF_INET;
end.sin_addr.s_addr=inet_addr(argv[2]);
endip=inet_addr(argv[2]);
HANDLE hthread;
while(htonl(startip)<=htonl(endip)){
if(threadnumcounter>threadnumlimit){
Sleep(5000);//等待5000ms
continue;
}
DWORD Threadid; //线程运行
sockaddr_in * pipaddrtemp=new(sockaddr_in);
if(!pipaddrtemp){
cout<<"memory alloc failed"<<endl;
return;
}
*pipaddrtemp=dest;
//创建新线程
clock_t start;
start=clock();
hthread=CreateThread(NULL,NULL,FindIp,(LPVOID)pipaddrtemp,NULL,&Threadid);
long i=60000000L;
while(i--)
;
TerminateThread(hthread,0);
InterlockedDecrement(aa); //多线程同步
memset(&from,0,sizeof(from));
startip=htonl(htonl(startip)+1);//将主机的无符号长整形数转换成网络字节顺序。
dest.sin_addr.s_addr=startip;
}
while(threadnumcounter!=0){
Sleep(2000);
return;
}
}
//填充ICMP数据包
void fill_icmp_data(char * icmp_data,int datasize){
Icmpheader *icmp_hdr;
char *datapart;
icmp_hdr=(Icmpheader*)icmp_data;
icmp_hdr->type = ICMP_ECHO; //设置类型
icmp_hdr->id=(USHORT)GetCurrentThreadId();//设置其ID号为当前线程号
datapart=icmp_data+sizeof(Icmpheader); //计算出ICMP数据报的数据部分
memset(datapart,'A',datasize-sizeof(Icmpheader));//填入数据
}
//解析数据包
void decode_resp(char *buf,int bytes,struct sockaddr_in *from){
IpHeader *iphdr;
Icmpheader *icmphdr;
unsigned short iphdrlen;
iphdr=(IpHeader *)buf;
iphdrlen=iphdr->headlen * 4;
icmphdr=(Icmpheader *)(buf+iphdrlen);
//数据包太短 丢弃
if(bytes<iphdrlen+ICMP_MIN) return;//丢弃
if(icmphdr->type!=ICMP_ECHO_REPLY) return;// 丢弃
if(icmphdr->id!=(USHORT)GetCurrentThreadId()) return;//丢弃
cout<<"活动主机"<<inet_ntoa(from->sin_addr)<<endl;
}
//校验和函数:每16位进行异或然后取反
USHORT checksum(USHORT *buffer,int size)
{
unsigned long cksum=0;
while (size>1)
{cksum+=*buffer++;
size-=sizeof(USHORT);}
if(size){cksum+=*(UCHAR*)buffer;}
cksum=(cksum>>16)+(cksum & 0xffff);
cksum+=(cksum>>16);
return (USHORT)(~cksum);
}
DWORD WINAPI FindIp(LPVOID pipaddrtemp){ //线程调用子函数
InterlockedIncrement(aa);
char icmp_data[MAX_PACKET];
memset(icmp_data,0,MAX_PACKET);
int datasize=DEF_PACKET_SIZE;
datasize+=sizeof(Icmpheader);
fill_icmp_data(icmp_data,datasize);
((Icmpheader*)icmp_data)->checksum=0;
((Icmpheader*)icmp_data)->seq = 0;
//计算校验和后填入
((Icmpheader*)icmp_data)->checksum=checksum((USHORT*)icmp_data,datasize);
int bwrote=sendto(sockraw,icmp_data,datasize,0,(struct sockaddr*)pipaddrtemp,sizeof(dest));
int n=0;
if (bwrote==SOCKET_ERROR){
if(WSAGetLastError()==WSAETIMEDOUT){
cout<<"timed out"<<endl;
}
cout<<"sendto failed: "<<WSAGetLastError()<<endl;
ExitProcess(STATUS_FAILED);
n=1;
}
if(bwrote<datasize)
{cout<<"worte "<<bwrote<<" bytes"<<endl;
ExitProcess(STATUS_FAILED);
n=1;
}
int bread =recvfrom(sockraw,recvbuf,MAX_PING_PACKET_SIZE,0,(struct sockaddr*) &from,&fromlen);//经socket接收数据
if(bread==SOCKET_ERROR)//错误码
{if(WSAGetLastError()==WSAETIMEDOUT)
{cout<<"time out"<<endl;}
cout<<"recvform failed:"<<WSAGetLastError()<<endl;
ExitProcess(STATUS_FAILED);
n=1;
}
if(n==0)
decode_resp(recvbuf,bread,&from); //调用解析包函数
InterlockedDecrement(aa);
return 0;
}