首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

第一回发帖求各位大神赐教

2012-06-28 
第一次发帖求各位大神赐教~我想把一个“发现网络中活动主机”的程序改为多线程同时运作,加快速度,改了后没能

第一次发帖求各位大神赐教~
我想把一个“发现网络中活动主机”的程序改为多线程同时运作,加快速度,改了后没能得到预期效果,求帮忙看看有什么错误,第一次用多线程。。。好多不懂的。。。

C/C++ code
#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;} 



[解决办法]
1,每个线程都操作同一个RAW SOCKET ? 错

2,while(htonl(startip)<=htonl(endip))

错,换成ntohl。

3,startip=htonl(ntohl(startip)+1);
[解决办法]
仅供参考
C/C++ code
#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是一回事,无所谓对错,只不过看起来好看一点而已

热点排行