获取局域网内在线的所有主机名及其IP地址
                                Author:swun911
                             blog.sina.com.cn/swun
    偶想搜索到局域网内所有在线的主机并获得其地址,使用了API的WNetEnumResource和gethostbyname。实现倒是实现了,可就是特别的慢,请指教。不知道各位高手有什么妙招,请赐教!
    My Emai:[email protected]
    我实现该目的部分的代码如下:
//**************************************************************************************
    //获取主机名 
    do
    {
EnumLocal = (LPNETRESOURCE) GlobalAlloc( GPTR, dwBuffer ) ; 
dwResult = WNetEnumResource(hEnum,&dwEntries,EnumLocal,&dwBuffer); 
if( dwResult == NO_ERROR )
{
    int kyy=0;
    for( register DWORD i = 0 ; i < dwEntries ; i++ ) 
    {
CString Enumname;
Enumname = EnumLocal[i].lpRemoteName;
Enumname += " ";
Enumname +=EnumLocal[i].lpLocalName;
Enumname += " ";
Enumname +=EnumLocal[i].lpComment;
CString Filtrate = Enumname.Left(1);
if(Filtrate=='\\')
{
           CString Inputname,IPAddress;
   Inputname=Enumname.Right(Enumname.GetLength()-2);//去掉"\\"
   Inputname=Inputname.SpanExcluding(" ");//去掉空格及其以后的部分
   GetIPAddress(Inputname,IPAddress);
   userinfo[kyy].h_name=Inputname;
   userinfo[kyy].h_IPadd=IPAddress;
   userinfo[kyy+1].h_name="xxx";
   kyy++;
}
     }

      } while( dwResult != ERROR_NO_MORE_ITEMS ); 
//****************************************************************************
     //IP地址
     GetIPAddress(CString &HostName, CString &IPAddress)
     {
struct hostent FAR *pIPHostEnt=gethostbyname(HostName);
if (pIPHostEnt==NULL)
{
IPAddress=_T("获取地址失败!");
return GetLastError();
} LPSTR IPAddr=pIPHostEnt->h_addr_list[0];
if(IPAddr)
{
struct in_addr inAddr;
memmove(&inAddr,IPAddr,4);
IPAddress=inet_ntoa(inAddr);
if(IPAddress.IsEmpty())
{
IPAddress=_T("没有取得IP");
AfxMessageBox(IPAddress);
}
}
return 0;
     }

解决方案 »

  1.   

    WSADATA wsaData; 
    SOCKET sockListener;
    SOCKADDR_IN saUdpCli,saUdpServ;
    BOOL fBroadcast = TRUE;

    char sendBuff[40]= //查询包内容

    '\x30','\x26','\x02','\x01','\x00', 
    '\x04','\x06','\x70','\x75','\x62', 
    '\x6c','\x69','\x63','\xa0','\x19', 
    '\x02','\x01','\x03','\x02','\x01', 
    '\x00','\x02','\x01','\x00','\x30', 
    '\x0e','\x30','\x0c','\x06','\x08', 
    '\x2b','\x06','\x01','\x02','\x01', 
    '\x01','\x01','\x00','\x05','\x00' 
    }; 
    char recvBuff[600]; 
    int nSize,err,timeoutnum = 1;;
    ULONG HostIpAddr;
    int rv; 
    int ncount=0; 

    if(WSAStartup(MAKEWORD( 2, 2),&wsaData)!=0) 
    {
    printf("Winsocket start error!\n");
    return; 
    }

    sockListener=socket(AF_INET,SOCK_DGRAM,0); 
    err = setsockopt ( sockListener,
    SOL_SOCKET,
    SO_BROADCAST, 
    (CHAR *)&fBroadcast,
    sizeof ( BOOL )); 
    if ( SOCKET_ERROR == err ) return ;

    int TimeOut=3000;

    err = setsockopt ( sockListener, 
    SOL_SOCKET,
    SO_RCVTIMEO,
    (CHAR *) &TimeOut,
    sizeof (TimeOut)
    );
    if ( SOCKET_ERROR == err ) return ;

    saUdpCli.sin_family = AF_INET; 
    saUdpCli.sin_port = htons(0); 
    saUdpCli.sin_addr.s_addr = htonl(INADDR_ANY); 
    if(bind( sockListener, (SOCKADDR *)&saUdpCli, sizeof(SOCKADDR_IN))!=0) 

    printf("Can't bind socket to local port!Program stop.\n");
    return; 


    err = gethostname(recvBuff,sizeof(recvBuff));
    if ( SOCKET_ERROR == err )
    return ;

    struct hostent *hp = gethostbyname(recvBuff);
    if (!hp) return ;

    saUdpServ.sin_family = AF_INET; 

    memcpy(&(saUdpServ.sin_addr),hp->h_addr,hp->h_length);
    HostIpAddr=ntohl(saUdpServ.sin_addr.s_addr);

    saUdpServ.sin_addr.s_addr = htonl ( INADDR_BROADCAST ); 
    saUdpServ.sin_port = htons (SNMP_PORT);
    nSize = sizeof ( SOCKADDR_IN ); 
    if((rv = sendto ( sockListener,
    sendBuff,
    sizeof(sendBuff),0,
    (SOCKADDR *) &saUdpServ,
    sizeof ( SOCKADDR_IN )))==SOCKET_ERROR) 

    printf("Send error!\n");
    closesocket(sockListener); 
    return; 

    printf("Send successful!\n");
    do // waiting to receive
    {
    if((rv=recvfrom ( sockListener,
    recvBuff,sizeof(recvBuff),0,
    (SOCKADDR *) &saUdpCli,&nSize))==SOCKET_ERROR) 

    if(WSAGetLastError()==WSAETIMEDOUT)
    {
    if (timeoutnum > 1 ) //Wait for 1 minute.
    break;
    else
    timeoutnum++;
    TRACE("Error \n");

    }
    }
    else
    {
    CString Ip(inet_ntoa ( saUdpCli.sin_addr ));
    m_pIpList->AddTail(Ip);
    TRACE("\t IP Adress-> %s \n",Ip);


    }while(TRUE);
    closesocket(sockListener); 
      

  2.   

    用 SendArp() 这个函数  获得0~255 他们的mac地址
    得到了就是在线  得不到就是没在
    开100个线程 处理0~99  发送后等待1秒  得到了就说明在线
    然后1秒后处理100~199..如此循环
    最多2~3秒就ok了