第一次发帖求各位大神赐教~
我想把一个“发现网络中活动主机”的程序改为多线程同时运作,加快速度,改了后没能得到预期效果,求帮忙看看有什么错误,第一次用多线程。。。好多不懂的。。。
#include "scanhost.h"WSADATA wsadata;SOCKET sockraw;//原始套接字struct sockaddr_in dest,end;//dest:搜索目的IP,end:搜索终止IPunsigned int addr=0;//IP地址long threadnumcounter=0,threadnumlimit=10;//线程个数及最大允许线程数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)//开始使用Ws2_32.dll { 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; 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; DWORD Threadid; DWORD*TID=&Threadid; while(htonl(startip)<=htonl(endip)) { if(threadnumcounter>threadnumlimit) { Sleep(5000); continue; } sockaddr_in * pipaddrtemp=new(sockaddr_in); if(!pipaddrtemp) { cout<<"memory alloc failed"<<endl; return; } *pipaddrtemp=dest; //创建新线程 clock_t start; start=clock(); CreateThread(NULL,NULL,FindIp,(LPVOID)pipaddrtemp,NULL,TID++);; startip=htonl(htonl(startip)+1); dest.sin_addr.s_addr=startip; } while(threadnumcounter!=0)//还有未完结的线程? { Sleep(2000); return; } //return;}void fill_icmp_data(char * icmp_data,int datasize)//填充icmp数据报{ Icmpheader *icmp_hdr; char *datapart; icmp_hdr=(Icmpheader*)icmp_data; icmp_hdr->type = ICMP_ECHO; icmp_hdr->id=(USHORT)GetCurrentThreadId(); datapart=icmp_data+sizeof(Icmpheader); 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;}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);//线程数目+1 struct sockaddr_in from;//from为接收的ICMP包的源IP int fromlen=sizeof(from); char icmp_data[MAX_PACKET];//MAX_PACKET是数据报最大可能的长度 memset(icmp_data,0,MAX_PACKET);//将数据报清空初始化 int datasize=DEF_PACKET_SIZE;//数据报报文体的缺省长度 datasize+=sizeof(Icmpheader);//加上报头的长度 fill_icmp_data(icmp_data,datasize);//填充icmp数据报 ((Icmpheader*)icmp_data)->checksum=0;//先将校验和置0 ((Icmpheader*)icmp_data)->seq = 0;//序列号为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; InterlockedDecrement(aa); return 0; } if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timed out"<<endl; InterlockedDecrement(aa); return 0; } if(bwrote<datasize) { cout<<"worte "<<bwrote<<" bytes"<<endl; InterlockedDecrement(aa); return 0; } //接收数据报 char * recvbuf=new char[MAX_PING_PACKET_SIZE]; int bread=SOCKET_ERROR; long i=60000000L; while(i--) { bread=recvfrom(sockraw,recvbuf,MAX_PING_PACKET_SIZE,0,(struct sockaddr*) &from,&fromlen); if(bread!=SOCKET_ERROR)break; } if(bread==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"time out"<<endl; } cout<<"recvform failed:"<<WSAGetLastError()<<endl; n=1; } //去掉IP报头,判断是否是此线程数据报,输出此数据报IP地址 if(n==0) decode_resp(recvbuf,bread,&from); InterlockedDecrement(aa);//线程数目-1 return 0;}
#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
[解决办法]
htonl 实际上和ntohl是一回事,无所谓对错,只不过看起来好看一点而已