我想快速搜索所有主机,我已经试过以下方法,注意,我强调的是快速
1.用ping,当然可以,但是如果要在程序中实现不大合理,而且我觉得速度也快不到哪里去
2.用winpcap发送arp请求包可以获得,但是获取时间不确定,而且获取速度不算太快
3.用SendARP函数,对于需要扫描255个主机时简直太慢了,不能忍受,感觉程序都无法响应了。于是我尝试着开255个线程分别调用SendARP函数,结果发现大多数SendArp都调用失败,错误值是31。不知道为什么
4.看到网上有人使用先枚举网络资源,再获取主机信息,然后有主机名获取IP,最后由IP获取MAC的方法,我觉得速度也快不到哪里去(这个没有具体试过)

解决方案 »

  1.   

    推荐使用方式 4, 也是最正规的方法呵呵^_^源码://struct in_addr *ptr; // 检索IP地址     DWORD dwScope = RESOURCE_CONTEXT;
        NETRESOURCE *NetResource = NULL;
        HANDLE hEnum;
        WNetOpenEnum( dwScope, NULL, NULL, 
                 NULL, &hEnum );
        if ( hEnum )
    {
        DWORD Count = 0xFFFFFFFF;
        DWORD BufferSize = 2048;
        LPVOID Buffer = new char[2048];
        WNetEnumResource( hEnum, &Count, 
            Buffer, &BufferSize );
        NetResource = (NETRESOURCE*)Buffer;    char szHostName[200];
        unsigned int i;    for ( i = 0;i < BufferSize/sizeof(NETRESOURCE);i++, NetResource++ )
        {
            if ( NetResource->dwUsage ==RESOURCEUSAGE_CONTAINER &&NetResource->dwType ==RESOURCETYPE_ANY )
            {
                if ( NetResource->lpRemoteName )
                {
                    CString strFullName =NetResource->lpRemoteName;
                    if ( 0 ==strFullName.Left(2).Compare("\\\\") )   
                        strFullName =strFullName.Right(strFullName.GetLength()-2);
                    gethostname( szHostName,strlen( szHostName ) );
                    host = gethostbyname(strFullName);
                    if(host == NULL) continue; 
                    strTemp.Format("%s",strFullName);
                    m_List.InsertItem(i,strTemp,0);         // 获得地址添加到列表
                }
            }
        }
        delete Buffer;
        WNetCloseEnum( hEnum );
      

  2.   

    对了,这个不是获得IP,只是获得了主机名字...-_-b再用gethostbyname转换一下就OK了^_^不好意思,多复制了一行,这个不要了-_-b //struct in_addr *ptr;
      

  3.   

    第四种方法,网上邻居也是采用netenum api,codeproject上有个例子
    www.codeproject.com/treectrl/pathpicker.asp
      

  4.   

    谢谢你们,piggyxp,请问方法4的效率怎么样,也就是说速度怎么样呢?
    另外你能告诉我为什么多线程调用SendARP就会失败么?谢谢叻
      

  5.   

    gracezhu(eutom),谢谢你
    我也知道网上邻居是采用的netenum,但是难道不觉得网上邻居打开很慢么?!我就是觉得太慢了啊,所以就想问有没有快一点的方法,呵呵
      

  6.   

    SendARP可以在多线程中调用的,只是SendARP只能扫描本网段的主机
      

  7.   

    wwww2() 你好
    我在多线程中调用失败啊,错误值都是31,不知道为什么,能指点一下么?!
    线程函数大概如下
    DWORD WINAPI GetMacByIP(LPVOID lParam)

         char * szIp=(char *)lParam;
         ULONG szMac[2];
         ULONG puMacLen=6;
         int ret;     
         ret=SendARP(szIp,0,szMac,&puMacLen);
         ....
         return ret;
    }
    不知道为什么
    }
      

  8.   

    不好意思,上面写错了一点
    ret=SendARP(inet_addr(szIp),0,szMac,&puMacLen);不知道为什么,如果循环调用,成功,只不过速度很慢如果开多线程,很多调用都失败,返回值都是31
      

  9.   

    线程函数
    DWORD WINAPI ArpThread(LPVOID lParam)
    {
    char * szIp=(char *)lParam;
    ULONG pMac[2];
    ULONG pulen=6;
    int ret;
    if ((ret=SendARP(inet_addr(szIp),0,pMac,&pulen))==0)
    {
    PBYTE pbyte=(PBYTE)pMac;
    for (int i=0;i<5;i++)
    {
    TRACE("%02X-",pbyte[i]);
    }
    TRACE("%02X",pbyte[5]);

    }
    else
    {
    TRACE("SendARP Error %d",ret);
    }
    return 0;
    }开多线程调用
    void CTestArpDlg::OnButton1() 
    {
    // TODO: Add your control notification handler code here
    HANDLE hthread[255];
    CString IpSuffix="192.168.10.";
    CString strIp;
    for (int i=0;i<255;i++)
    {
    strIp.Format("%d",i+1);
    strIp=IpSuffix+strIp;
    hthread[i]=CreateThread(NULL,0,ArpThread,strIp.GetBuffer(0),0,NULL);
    }
    WaitForMultipleObjects(255,hthread,TRUE,INFINITE);}
      

  10.   

    这两天看到一个《基于UDP协议的网段扫描器》,大致代码如下,可以得到工作组,机器名,用户名和MAC地址
    BYTE bs[50]={0x0,0x00,0x0,0x10,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x43,0x4b,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x0,0x0,0x21,0x0,0x1};
    HANDLE wait_handle;m_UDPSocket.SendTo((void*)bs,50,destPORT,m_strIP,0);//向指定的ip发数据报
    WaitForSingleObject(
    wait_handle,        // 等待事件的句柄
    nWait   // 超时
    );
    ResetEvent(wait_handle);//将事件重新置回非触发状态void CNBTSTATDlg::OnReceive()
    {
    BYTE Buf[500];
    CString str,strIP,strHost,strHex,strMac,Host,Group,User;
    UINT dport;
    m_UDPSocket.ReceiveFrom(Buf,500,strIP,dport,0);//接收数据
        //如果接收到的ip为空或者与原来接收到的ip相同,则返回
    if(strIP==(char)NULL||strIP==strOldIP)return;
    strOldIP=strIP;
    int index=m_ListView.InsertItem(0,strIP);//将ip插入ListView
    strHost=""; //机器名字
    strHex="";//MAC地址
    User="?";//
    Host="\\";
    int tem=0,num=0;
    bool bAdd=true;
    //根据数据报规则取出相应的信息
    for(i=57;i<500;i++) //57-72
    {
    if(Buf[i]==0xcc)break; 
    if(Buf[i]==0x20)bAdd=false;
    if(bAdd)
    {
    str.Format("%c",Buf[i]);
    if(Buf[i]>=' ')strHost+=str; str.Format("%02x.",Buf[i]);
    strHex+=str;
    } if((++tem)%18==0)
    {
                bAdd=true; 
    strHost.TrimRight((char)NULL);
    if(strHost=="")
    {
        strMac.Delete(17,strMac.GetLength()-17);
    m_ListView.SetItem(index,4,LVIF_TEXT,strMac, 0, 0, 0,0);
    break;
    }
    if(num==0&&strHost!="")
    {
    m_ListView.SetItem(index,2,LVIF_TEXT,strHost, 0, 0, 0,0);
    Host=strHost;
    num++;
    }
    else
    {
    if(Host!=strHost&&num==1&&strHost!="")
    {
    m_ListView.SetItem(index,1,LVIF_TEXT,strHost, 0, 0, 0,0);
    Group=strHost;
        num++;
    }
    else 
    {
    if(strHost!=Host&&strHost!=Group&&num==2&&strHost!="")
    {
    User=strHost;
    if(User!="__MSBROWSE__")
    {
    m_ListView.SetItem(index,3,LVIF_TEXT,User, 0, 0, 0,0);
    num++;
    }
    }
    } }

    strMac=strHex;
    strHost="";
    strHex="";

    }

    }
    //触发事件,导致线程函数的继续执行
    SetEvent(wait_handle);
    }
      

  11.   

    我认识为用"2.用winpcap发送arp请求包可以获得,但是获取时间不确定,而且获取速度不算太快"这种方法好,速度最快的,获取时间可以自己设置定时器来设置超时吧
      

  12.   

    to wjl_2001(wjl_2001),这种方法我试过,速度还行,但不算太快,大概是几秒钟。关键是获取时间不确定问题,因为是自己发arp请求包,然后开一个线程接收并且分析收到的数据包,至于什么时候arp包接收完毕(也就是所有存活主机都已发回arp应答包) ,不是太好确定,唯一一种方法就是主线程发送了arp请求包后,Sleep(3000),然后再查看获取的ip/mac对记录,但是这种方法具有不确定性,因为不能保证3秒钟以后,就一定收到所有存活主机的arp应答包
      

  13.   

    to gaobaotian(gaobaotian),谢谢你,不知道效率怎么样,我试试看
      

  14.   

    发udp包,监听端口不可达回应包即可
      

  15.   

    呵呵呵,说到udp那还扫描什么呢?扫描其实是最慢的办法直接发udp广播,然后接收到这个广播的主机都给服务器回个自己的ip/mac/hostname信息我想这个办法也不错呵呵^_^
      

  16.   

    我认为用方法2好,不管对方开不开端口,给不给ping,用方法2都可以扫到
    局域网内,我都用此方法,一个字:快,基本上10ns内就可能得到反馈信息,极少出现100毫秒以上才反馈的(未遇到过)
      

  17.   

    另外,楼主说的"大概是几秒钟"是指扫描一个C段吗(255的IP)?
    你可能调整几微秒发送一个包都可以啊
      

  18.   

    to wjl_2001(wjl_2001) 
    不是发送包的速度,这个很好控制。关键是处理回送的arp应答包很伤脑筋啊!
    关键如果要保证所有回送的arp包能够收到,肯定时间要长一点啊,因为是开线程处理回送的包,只有保证线程有足够的cpu时间,才可能收到所有包。比如,现在机器上现在正在运行一个高优先级,大计算量的线程,那么很可能我的线程得到运行的机会很少,所以只有设置足够长的时间才能保证包都收到并被处理。
      

  19.   

    另外,to PiggyXP(【小猪】●你快乐于是我快乐)
    你提供的代码只是枚举和我同一个工作组的主机吗?我运行以后怎么只能得到和我同一工作组的主机,而得不到其它主机啊!怎么回事呢
      

  20.   

    啊?我还没有注意呢, 这段代码我没有试,是我从一份代码里面分离出来的-_-b不过很有可能,因为它的基本原理和网上邻居是一样的,都是基于NetBIOS的接口所以以工作组为单位是很有可能的-_-b
      

  21.   

    楼主:
    "关键如果要保证所有回送的arp包能够收到,肯定时间要长一点啊,因为是开线程处理回送的包,只有保证线程有足够的cpu时间,才可能收到所有包。比如,现在机器上现在正在运行一个高优先级,大计算量的线程,那么很可能我的线程得到运行的机会很少,所以只有设置足够长的时间才能保证包都收到并被处理。"
    如果你是这么考虑的话,任何扫描都不可能快速的,你说呢?
      

  22.   

    to wjl_2001(wjl_2001) ,我举这个例子的意思是说明发送arp包来获取ip/mac对在时间上不确定性,很不好控制,所以为了保证能够收到所有包,只有设置一个较长时间等待
    但是其他方法就比较好控制一点,比如说SendARP,可能也会遇到上面的情况,但是它具有确定性,一旦它调用返回的时候,就可以得到mac地址,即使时间再长,但是这个时间是确定的,我是这个意思,就是想知道一个在时间上具有确定性,并且时间相对较短的方法,呵呵
      

  23.   

    不行的话,只能想别的办法了.-_-b其实开 255 的线程实在是多了,因为我以前做扫描器的时候,发现系统开200的线程正好达到系统性能的临界点,多了话反而会造成性能的急剧下降,我的电脑是 P4 2.4 G的SendARP函数我没有用过,但是我用winpcap做过很多arp包的试验,其实arp包的返回是非常快的,如果觉得不够保险,可以对某主机一次发多个数据包,估计局域网的环境下应该是没有问题的
      

  24.   

    SendARP可以的多线程呀,我写过程序的,没有出错啊,在开启线程之间Sleep以下就好了
      

  25.   

    to:PiggyXP就算是开255个线程,其实同时运行的线程也只不过10几个而已,因为如果目标主机存在的话,SendARP函数会很快返回的。
    我就写过这么个程序,扫描时对系统性能没什么影响
      

  26.   

    虽然是C++Builder的源代码,但是是从VC移植来的,VC的代码找不到了//---------------------------------------------------------------------------#include <vcl.h>
    #include <iphlpapi.h>
    #include <windows.h>
    #include <winsock2.h>
    #include <windowsx.h>
    #pragma hdrstop#include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"typedef struct _setup_info
    {
    PIP_ADAPTER_INFO pAdInfo;
    DWORD AdapIndex;
    }SETUP_INFO,*PSETUP_INFO;TForm1 *Form1;
    SETUP_INFO SetupInfo;//---------------------------------------------------------------------------AnsiString __stdcall sg(AnsiString str,int n) 

    int l,i; 
    AnsiString qq(str); 
    l=qq.Length(); 
    AnsiString p(str); 
    char a[]="\r\n"; 
    int j,k=0; 
    for(j=1;j< l;j++) 

    i=1; 
    while(qq[j]!=a[0] && qq[j+1]!=a[1]) 

    p[i++]=qq[j]; 
    j++; 

    k++; 
    if((k-1)==n) 
    break; 

    p[i]=' ';p[i+1]=' '; 
    return (p); 
    }//---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------BOOL FormatMACStr(ULONG *pMacAddr,char *szMAC)
    {
        if(pMacAddr[0]==pMacAddr[1])return FALSE;
        return TRUE;
    }//----------------------------------------------------------------------------DWORD WINAPI EnumActiveHost(IPAddr ipAddr)
    {
        char szMAC[18]="";
        char szComputerName[256]="";
        in_addr inaddr;
    ULONG pMacAddr[2],ulLen=6;
    ulLen=6;
    FillMemory(pMacAddr,sizeof(pMacAddr),0xff);
    SendARP(ipAddr,0,pMacAddr,&ulLen);
    inaddr.S_un.S_addr=ipAddr;
    if(FormatMACStr(pMacAddr,szMAC))
        {
            TListItem *ListItem=Form1->ListView1->Items->Add();
            ListItem->Caption=inet_ntoa(inaddr);
            ListItem->SubItems->Add(szMAC);
            ListItem->SubItems->Add(szComputerName);
        }
    return 0;
    }//------------------------------------------------------------------DWORD ScanActiveHost(LPVOID lpParameter)
    {
    DWORD ThreadId;
        HANDLE hThread[255];
    IPAddr ipAddr=inet_addr("192.168.253.0");
    FlushIpNetTable(SetupInfo.AdapIndex);
        Form1->StatusBar1->Panels->Items[1]->Text=" 正在扫描...";
        Form1->ListView1->Items->Clear();
    for(int i=0;i<255;i++)
    {
            Form1->ProgressBar1->StepBy(1);
    ipAddr=htonl((htonl(ipAddr)+1));
    hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)EnumActiveHost,(LPVOID)ipAddr,0,&ThreadId);
    }
        WaitForMultipleObjects(255,hThread,TRUE,INFINITE);
        for(int i=0;i<255;i++)
        {
            CloseHandle(hThread[i]);
        }
        Form1->StatusBar1->Panels->Items[1]->Text=" 扫描结束";
        Form1->ProgressBar1->Position=0;
        Sleep(1000);
        Form1->StatusBar1->Panels->Items[1]->Text="  共 "+IntToStr(Form1->ListView1->Items->Count)+" 台活动主机";
        Form1->ToolButton1->Enabled=TRUE;
        Form1->ToolButton2->Enabled=TRUE;
        return TRUE;
    }//------------------------------------------------------------------DWORD EnumAdapters(HWND hCombo)
    {
    int comboindex=0;
    PIP_ADAPTER_INFO pTemp;
    ULONG IfIndex;
        HMODULE hModule=LoadLibrary("iphlpapi.dll");
        if(hModule==NULL)
            return FALSE;
        try{
      GetAdaptersInfo(NULL,&IfIndex);
    SetupInfo.pAdInfo=pTemp=(PIP_ADAPTER_INFO)VirtualAlloc(NULL,IfIndex,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    GetAdaptersInfo(pTemp,&IfIndex);
        }catch(Exception &exception)
        {
        Application->ShowException(&exception);
        }
    while(pTemp)
    {
    ComboBox_AddString(hCombo,pTemp->Description);
    ComboBox_SetItemData(hCombo,comboindex,pTemp);
    pTemp=pTemp->Next;comboindex++;
    }return TRUE;
    }//------------------------------------------------------------------
    void __fastcall TForm1::FormShow(TObject *Sender)
    {
        EnumAdapters(Form1->ComboBox1->Handle);
        ComboBox_SetCurSel(Form1->ComboBox1->Handle,0);
    }
    //---------------------------------------------------------------------------void __fastcall TForm1::ToolButton2Click(TObject *Sender)
    {
        HANDLE hFile;
        char szPath[MAX_PATH];
        AnsiString String;
        DWORD nobw;
        GetCurrentDirectory(MAX_PATH,szPath);
        Form1->SaveDialog1->InitialDir=szPath;
        if(!Form1->SaveDialog1->Execute())return;
        hFile=CreateFile(SaveDialog1->FileName.c_str(),FILE_ALL_ACCESS,FILE_SHARE_READ,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile==INVALID_HANDLE_VALUE)
        {
            if(MessageBox(Form1->Handle,"文件已存在,是否要替换?","提示",MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)==IDYES)
                hFile=CreateFile(SaveDialog1->FileName.c_str(),FILE_WRITE_DATA,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            else return;
        }//if(hFile==INVALID_HANDLE_VALUE)ShowMessage(IntToStr(GetLastError()));
        for(int i=0;i<ListView1->Items->Count;i++)
        {
            String=String+ListView1->Items->Item[i]->Caption+"\t"+sg(ListView1->Items->Item[i]->SubItems->Text,0);
        }
        WriteFile(hFile,String.c_str(),String.Length(),&nobw,NULL);
        CloseHandle(hFile);
    }
    //---------------------------------------------------------------------------void __fastcall TForm1::ToolButton1Click(TObject *Sender)
    {
        DWORD ThreadId;
        CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ScanActiveHost,(LPVOID)NULL,0,&ThreadId));
        ToolButton1->Enabled=FALSE;
        ToolButton2->Enabled=FALSE;
    }
    //---------------------------------------------------------------------------
      

  27.   

    TO: tabris17(四不象)     呵呵我不是说SendARP不行,我只是说winpcap发送arp包可以实现    我没有用过SendARP,只是看到楼主说程序无法响应    感谢你带来这么好的东西,如果这样可以的话,就是一个很好的方案了,使用winpcap的话还要另外装驱动,麻烦
      

  28.   

    啊,忘记说了,上面的代码这里有点问题WaitForMultipleObjects(255,hthread,TRUE,INFINITE);WaitForMultipleObjects 函数最多等待 MAXIMUM_WAIT_OBJECTS 个句柄,MAXIMUM_WAIT_OBJECTS 好像是65把,用for语句改进一下就好了我贴出来的是旧版本的代码,该本版不会判断局域网的子网掩码,星期一贴上新的
      

  29.   

    to tabris17(四不象) ,你说多线程调用SendArp没有问题吗?但是为什么我的有问题,我的代码就贴在上面在,几乎和你的一样
    for(int i=0;i<255;i++)
    {
            Form1->ProgressBar1->StepBy(1);
    ipAddr=htonl((htonl(ipAddr)+1));
    hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)EnumActiveHost,(LPVOID)ipAddr,0,&ThreadId);
    }
        WaitForMultipleObjects(255,hThread,TRUE,INFINITE);
        for(int i=0;i<255;i++)
        {
            CloseHandle(hThread[i]);
        }
        Form1->StatusBar1->Panels->Items[1]->Text=" 扫描结束";
        Form1->ProgressBar1->Position=0;
        Sleep(1000);
    不过也是忘记了WaitForMultipleObjects(255,hthread,TRUE,INFINITE);只能等待64个对象,呵呵,不知道是不是这个引起错误了,我马上试试!
    另外,你说的
    多线程呀,我写过程序的,没有出错啊,在开启线程之间Sleep以下就好了
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    但是我看你程序里面开启线程之间并没有Sleep啊,而是开启所有线程,并且线程结束了以后才Sleep(1000)啊,究竟是怎么回事。另外,调用Sleep和不调用Sleep有区别么??
      

  30.   

    to tabris17(四不象) ,哦,明白了,呵呵,Sleep()的作用是让线程能够迅速取得参数,以免参数被后面的线程的参数所改变。呵呵,现在没有错了,谢谢你啊,呵呵不过,即使开了255个线程,得到所有存活主机的速度还是很慢啊!!你获取的速度怎么样?
      

  31.   

    呵呵,搞定了,采用多线程调用SendARP的方法不错,效率很高(我的局域网11台机器在线,几秒钟就搞定:))不用每开一个线程就Sleep(),这样速度很慢,可以预先定义一个CString szIp[255];数组,作为255个线程的参数,下面是程序的大概:
    //全局变量
    typedef struct ipmac
    {
    char szIp[16];
    char szMac[6];}IPMAC;
    IPMAC host[255];
    int k=0;
    CRITICAL_SECTION cs;
    /*线程函数,用来查询IP对应的MAC地址*/
    DWORD WINAPI ArpThread(LPVOID lParam)
    {
    char * szIp=(char *)lParam;
    ULONG pMac[2];
    ULONG pulen=6;
    int ret;
        TRACE(szIp);
    if ((ret=SendARP(inet_addr(szIp),0,pMac,&pulen))==0)
    {
    EnterCriticalSection(&cs); //多线程同步,呵呵:0
    strcpy(host[k].szIp,szIp);
    PBYTE pbyte=(PBYTE)pMac;
    for (int i=0;i<5;i++)
    {
    host[k].szMac[i]=pbyte[i];
    TRACE("%02X-",pbyte[i]);
    }
    TRACE("%02X",pbyte[5]);
    host[k].szMac[5]=pbyte[5];
    k++;
    LeaveCriticalSection(&cs);

    }
    else
    {
    TRACE("SendARP Error %d",ret);
    }
    return 0;
    }/*枚举局域网内所有主机,并将IP/MAC对插入ListBox中显示*/
    void CTestArpDlg::OnButton1() 
    {
    // TODO: Add your control notification handler code here
    HANDLE hthread[254];
    CString IpSuffix="192.168.10.";
    CString strIp[254]; 
    InitializeCriticalSection(&cs);
    for (int i=0;i<254;i++)
    {
    strIp[i].Format("%d",i+1);
    strIp[i]=IpSuffix+strIp[i];
    hthread[i]=CreateThread(NULL,0,ArpThread,strIp[i].GetBuffer(0),0,NULL); 

    }
             /*呵呵,因为一次只能等待 64个内核对象,所以只有分几次了*/
             /*当然也可以用循环了*/
    WaitForMultipleObjects(64,hthread,TRUE,INFINITE);
    WaitForMultipleObjects(64,&hthread[64],TRUE,INFINITE);
    WaitForMultipleObjects(64,&hthread[128],TRUE,INFINITE);
    WaitForMultipleObjects(62,&hthread[192],TRUE,INFINITE);
        DeleteCriticalSection(&cs);
        CString temp;
    for (i=0;i<k;i++)
    {
    PBYTE pmac=(PBYTE)host[i].szMac;
    temp.Format("%s(%02x-%02x-%02x-%02x-%02x-%02x)",host[i].szIp,pmac[0],pmac[1],pmac[2],pmac[3],pmac[4],pmac[5]);
    m_list.AddString(temp);
    }
    }
      

  32.   

    呵呵,另外说一下,关于使用WNet函数(WNetEnumResource,WNetEnumResource),我觉得不保险,(效率还行,但是好像枚举的主机不全,不知道为什么)我在以前的帖子中查到
    "
    列举网络上所有资源http://www.ittide.com/document/source/netware/network.zip
    "
    使用它的程序,除了自己工作组内的主机外,还可以列出自己工作组之外的主机,但是还是不全。所以还是建议大家用多线程SendARP方法,速度快,而且枚举的主机全,呵呵,特别推荐!呵呵,好,问题解决了,如果大家没有什么问题,我就结贴了!
      

  33.   

    呵呵呵,不错不错,终于能有结果了收藏一下这个帖子badguy2002(风一样的男孩)看到大家都这么辛苦的份上,不把帖子加到100分啊^_^
      

  34.   

    //---------------------------------------------------------------------------#include <vcl.h>
    #include <iphlpapi.h>
    #include <windows.h>
    #include <winsock2.h>
    #include <windowsx.h>
    #pragma hdrstop#include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"typedef struct _setup_info
    {
    PIP_ADAPTER_INFO pAdInfo;
    DWORD AdapIndex;
    }SETUP_INFO,*PSETUP_INFO;TForm1 *Form1;
    SETUP_INFO SetupInfo;
    WSADATA wsadata;//---------------------------------------------------------------------------AnsiString __stdcall sg(AnsiString str,int n)  //保存扫描列表所用到的格式化字符串的函数

    int l,i; 
    AnsiString qq(str); 
    l=qq.Length(); 
    AnsiString p(str); 
    char a[]="\r\n"; 
    int j,k=0; 
    for(j=1;j< l;j++) 

    i=1; 
    while(qq[j]!=a[0] && qq[j+1]!=a[1]) 

    p[i++]=qq[j]; 
    j++; 

    k++; 
    if((k-1)==n) 
    break; 

    p[i]=' ';p[i+1]=' '; 
    return (p); 
    }//---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------int GetHostNumber(IPAddr *lpAddr) //根据子网掩码得到以太网的主机容纳数目
    {
        //*lpAddr=inet_addr("192.168.253.0");
        IPAddr ipaddr,maskaddr;
        HWND hWnd=Form1->ComboBox1->Handle;
        ipaddr=inet_addr(((PIP_ADAPTER_INFO)ComboBox_GetItemData(hWnd,ComboBox_GetCurSel(hWnd)))->IpAddressList.IpAddress.String);
        maskaddr=inet_addr(((PIP_ADAPTER_INFO)ComboBox_GetItemData(hWnd,ComboBox_GetCurSel(hWnd)))->IpAddressList.IpMask.String);
        *lpAddr=maskaddr&ipaddr;
        return htonl(~maskaddr)-1;
    }//---------------------------------------------------------------------------void GetRemoteComputerName(IPAddr ipAddr,char *szComputerName) //根据IP地址得到计算机名
    {
        struct hostent* pHost=gethostbyaddr((char*)&ipAddr,4,AF_INET);
        if(pHost!=NULL)
            lstrcpy(szComputerName,pHost->h_name);
    }//---------------------------------------------------------------------------BOOL FormatMACStr(ULONG *pMacAddr,char *szMAC)
    {
        if(pMacAddr[0]==pMacAddr[1])return FALSE;
        for(int i=0;i<6;i++)
        {
            wsprintf(szMAC+i*3,"%02X",((BYTE *)pMacAddr)[i]);
            szMAC[i*3+2]='-';
        }szMAC[17]='\0';
        return TRUE;
    }//----------------------------------------------------------------------------DWORD WINAPI EnumActiveHost(IPAddr ipAddr)
    {
        char szMAC[18]="";
        char szComputerName[256]="";
        in_addr inaddr;
        ULONG pMacAddr[2],ulLen=6;
        FillMemory(pMacAddr,sizeof(pMacAddr),0xff);
        SendARP(ipAddr,0,pMacAddr,&ulLen);
        inaddr.S_un.S_addr=ipAddr;
        if(FormatMACStr(pMacAddr,szMAC))
        {
            GetRemoteComputerName(ipAddr,szComputerName);
            TListItem *ListItem=Form1->ListView1->Items->Add();
            ListItem->Caption=inet_ntoa(inaddr);
            ListItem->SubItems->Add(szMAC);
            ListItem->SubItems->Add(szComputerName);
        }return 0;
    }//------------------------------------------------------------------DWORD ScanActiveHost(LPVOID lpParameter)
    {
        DWORD ThreadId;
        int hostnum;
        HANDLE *hThread;
    IPAddr ipAddr;
        hostnum=GetHostNumber(&ipAddr);
        hThread=(HANDLE *)VirtualAlloc(NULL,4*hostnum,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    FlushIpNetTable(SetupInfo.AdapIndex);
        Form1->StatusBar1->Panels->Items[1]->Text=" 正在扫描...";
        Form1->ListView1->Items->Clear();
    for(int i=0;i<hostnum;i++)
    {
            Sleep(10);
            Form1->ProgressBar1->StepBy(1);
    ipAddr=htonl((htonl(ipAddr)+1));
    hThread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)EnumActiveHost,(LPVOID)ipAddr,0,&ThreadId);
    }//MAXIMUM_WAIT_OBJECTS
        for(int i=0;i<=hostnum/MAXIMUM_WAIT_OBJECTS;i++)
            WaitForMultipleObjects(i==hostnum/MAXIMUM_WAIT_OBJECTS?MAXIMUM_WAIT_OBJECTS:hostnum%MAXIMUM_WAIT_OBJECTS,hThread+i*MAXIMUM_WAIT_OBJECTS,TRUE,INFINITE);
        for(int i=0;i<hostnum;i++)
            CloseHandle(hThread[i]);
        Form1->StatusBar1->Panels->Items[1]->Text=" 扫描结束";
        Form1->ProgressBar1->Position=0;
        Sleep(1000);
        Form1->StatusBar1->Panels->Items[1]->Text="  共 "+IntToStr(Form1->ListView1->Items->Count)+" 台活动主机";
        Form1->ToolButton1->Enabled=TRUE;
        Form1->ToolButton2->Enabled=TRUE;
        VirtualFree(hThread,4*hostnum,MEM_DECOMMIT|MEM_RELEASE);
        return TRUE;
    }//------------------------------------------------------------------DWORD EnumAdapters(HWND hCombo)
    {
    int comboindex=0;
    PIP_ADAPTER_INFO pTemp;
    ULONG IfIndex;
        try{
      GetAdaptersInfo(NULL,&IfIndex);
    SetupInfo.pAdInfo=pTemp=(PIP_ADAPTER_INFO)VirtualAlloc(NULL,IfIndex,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    GetAdaptersInfo(pTemp,&IfIndex);
        }catch(Exception &exception)
        {
        Application->ShowException(&exception);
        }
    while(pTemp)
    {
    ComboBox_AddString(hCombo,pTemp->Description);
    ComboBox_SetItemData(hCombo,comboindex,pTemp);
    pTemp=pTemp->Next;comboindex++;
    }return TRUE;
    }//------------------------------------------------------------------
    void __fastcall TForm1::FormShow(TObject *Sender)
    {
        if(WSAStartup(MAKEWORD(2,0),&wsadata)!=0)MessageBox(Form1->Handle,"Winsock 初始化出错!","错误",MB_OK|MB_ICONSTOP);
        EnumAdapters(Form1->ComboBox1->Handle);
        ComboBox_SetCurSel(Form1->ComboBox1->Handle,0);
    }
    //---------------------------------------------------------------------------void __fastcall TForm1::ToolButton2Click(TObject *Sender) //保存结果
    {
        HANDLE hFile;
        char szPath[MAX_PATH];
        AnsiString String;
        DWORD nobw;
        GetCurrentDirectory(MAX_PATH,szPath);
        Form1->SaveDialog1->InitialDir=szPath;
        if(!Form1->SaveDialog1->Execute())return;
        hFile=CreateFile(SaveDialog1->FileName.c_str(),FILE_ALL_ACCESS,FILE_SHARE_READ,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile==INVALID_HANDLE_VALUE)
        {
            if(MessageBox(Form1->Handle,"文件已存在,是否要替换?","提示",MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2)==IDYES)
                hFile=CreateFile(SaveDialog1->FileName.c_str(),FILE_WRITE_DATA,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            else return;
        }//if(hFile==INVALID_HANDLE_VALUE)ShowMessage(IntToStr(GetLastError()));
        for(int i=0;i<ListView1->Items->Count;i++)
        {
            String=String+ListView1->Items->Item[i]->Caption+"\t"+sg(ListView1->Items->Item[i]->SubItems->Text,0);
        }
        WriteFile(hFile,String.c_str(),String.Length(),&nobw,NULL);
        CloseHandle(hFile);
    }
    //---------------------------------------------------------------------------void __fastcall TForm1::ToolButton1Click(TObject *Sender) //开始扫描
    {
        DWORD ThreadId;
        CloseHandle(CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ScanActiveHost,(LPVOID)NULL,0,&ThreadId));
        ToolButton1->Enabled=FALSE;
        ToolButton2->Enabled=FALSE;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::ComboBox1Change(TObject *Sender)
    {
    HWND hWndCtrl=Form1->ComboBox1->Handle;
    SetupInfo.AdapIndex=((PIP_ADAPTER_INFO)ComboBox_GetItemData(hWndCtrl,ComboBox_GetCurSel(hWndCtrl)))->Index;
    //MessageBox(NULL,((PIP_ADAPTER_INFO)ComboBox_GetItemData(hWndCtrl,ComboBox_GetCurSel(hWndCtrl)))->AdapterName,"",1);
    }
    //---------------------------------------------------------------------------
      

  35.   

    楼主
    for (int i=0;i<255;i++)
    {
    strIp.Format("%d",i+1);
    strIp=IpSuffix+strIp;
    hthread[i]=CreateThread(NULL,0,ArpThread,strIp.GetBuffer(0),0,NULL);
    你不觉得第二次执行strIp=IpSuffix+strIp;会不对??????????????