用什么办法可以扫描本地所有的主机呢?
听说是向本地所有地址的137端口发送udp包 是这样吗?
如果是的话,请问他返回的是什么?是结构体还是其他什么呢?
用什么函数捕获呢?请高手指点.

解决方案 »

  1.   

    方式  4,  采用网上邻居的方法,但是只能枚举本工作组内的主机  
     
    源码:  
     
           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  );  
     
    ---------------------------------------------------------------  
     
    第四种方法,网上邻居也是采用netenum  api,codeproject上有个例子  
    www.codeproject.com/treectrl/pathpicker.asp  
     
      

  2.   

    如果大家都装了tcp/ip协议的话可以使用广播发送数据包的方法。
      

  3.   

    取本机的IP,取本机子网掩码,根据子网掩码确定本机的IP网段,然后使用广播发送数据包获取
      

  4.   

    关注!顺便问一下,像WNetEnumResource这样的函数列举共享资源只是列举到共享的文件夹列表,怎样列举文件呢?共享文件夹中的文件不算共享资源吗?
      

  5.   

    给你一个类的例程研究下
    #ifndef LAN_SOURCE_H
    #define LAN_SOURCE_H#include "Winsock2.h"
    #include "afxtempl.h"
    #include "Winnetwk.h"#define WM_GET_ONE_HOST WM_USER+1   //每次获得一个主机,则发送这个消息
    #define WM_GET_ONE_HOST_BYADDR WM_USER+3   //根据IP地址获取主机名称
    #define ERROR_ADDRESS 0
    #define A_ADDRESS 1
    #define B_ADDRESS 2
    #define C_ADDRESS 3
    #define OTHER_ADDRESS 4/*这个程序需要SDK库的支持
     *分别是Mpr.lib和Ws2_32.lib
     *//*定义主机信息存储结构*/
    typedef struct
    {
    char hostname[256];   //主机名称
    int hostname_len;     //长度
    int hostaddr[4];      //主机地址
    char wgname[256];     //工作组名称
    int wgname_len;       //长度
    int online;           //在线状态
    }hostmsg;class LANsource
    {
    public:
    LANsource(void);
    ~LANsource(void); /*初始化网络*/
    int Net_init();


    /*开始枚举*/
    DWORD Enum_NetWork(NETRESOURCE *vNewResource,HWND hWnd); /*获取一个主机信息*/
    int GetNextHost(char *HostName,int *HostName_len,char *HostAddr,int *Online); /*根据IP地址段扫描主机*/
    int ScanHostByAddr(char *HostAddrs,char *HostAddre,HWND hWnd); /*根据主机名称查询主机信息*/
    int ScanHostByName(char *HostName,HWND hWnd);private:

    /*程序使用的变量*/
    WSADATA wsaData; CList<hostmsg,hostmsg&> hostmsg_list;  //主机信息列表
    int nFlag;     //查询标志
    POSITION pos;  //列表中的位置标志 /*初始化网络枚举,该函数枚举当前连接资源*/
    HANDLE Connect_enum_init(NETRESOURCE *vNewResource);
    void msg(DWORD i);
    void PutList(NETRESOURCE *netresource,DWORD Count,HWND hWnd); /*分析IP地址的类型*/
    int ParasIP(char *Start_IP,char *End_IP,int *int_startip,int *int_endip); /*实际的扫描IP地址的函数*/
    int GetHostByAddr(int *startIP,int *endIP,int IPType,HWND hWnd); /*根据返回的Host获得hm结构*/
    void GetHostMsg(struct hostent *host,int *startIP,HWND hWnd); /*根据一个数组组合称为一个代表IP地址的字符串*/
    char *fmtIPString(int *IP);
    };
    #endif
      

  6.   

    #include "StdAfx.h"
    #include ".\lansource.h"LANsource::LANsource(void)
    {
    }LANsource::~LANsource(void)
    {
    WSACleanup();
    }//初始化Windows Socket库,执行成功返回0
    int LANsource::Net_init()
    {
    int vResult=WSAStartup(MAKEWORD(1,1),&wsaData);
    hostmsg_list.RemoveAll();           //清空列表 
    return vResult;
    }//初始化枚举,枚举当前的连接资源
    HANDLE LANsource::Connect_enum_init(NETRESOURCE *vNewResource)
    {
    DWORD dwType=RESOURCETYPE_ANY;
    HANDLE hEnum;
    nFlag=0; //准备枚举
    if(WNetOpenEnum(vNewResource?RESOURCE_GLOBALNET  : RESOURCE_CONTEXT,
     dwType,
     0,
     vNewResource?vNewResource:NULL,
     &hEnum)==NO_ERROR) return hEnum;
    return NULL;
    }
    DWORD LANsource::Enum_NetWork(NETRESOURCE *vNewResource,HWND hWnd)
    {
    DWORD vResult;
    HANDLE hEnum= Connect_enum_init(vNewResource);

    if(!hEnum) return 0; DWORD Count=0xFFFFFFFF;
    DWORD BufferSize=16384;
    void *Buffer=new char[16384]; do
    {
    NETRESOURCE *netresource =NULL;                  //设置网络资源结构指针,用于处理返回值
    vResult=WNetEnumResource(hEnum,&Count,Buffer,&BufferSize); netresource=(NETRESOURCE *)Buffer;
    if(vResult==NO_ERROR) PutList(netresource,Count,hWnd);
    }while(vResult!=ERROR_NO_MORE_ITEMS);

    return hostmsg_list.GetCount();

    }void LANsource::msg(DWORD i)
    {
    char a[20];
    _ultoa(i,a,10);
    AfxMessageBox(a);
    }/*从资源缓存中,获取主机信息,并添加到列表中*/
    void LANsource::PutList(NETRESOURCE *netresource,DWORD Count,HWND hWnd)
    {
       CList<NETRESOURCE,NETRESOURCE&> NetResource_List; for(unsigned int i=0;i<Count;i++,netresource++)
    {
    hostmsg hm;               //自定义的主机信息结构 //if(netresource->dwUsage && netresource->dwType)
    //{
    /*检查是否存在远程主机名*/
    char *tmpHostName;

    if(netresource->lpRemoteName && (netresource->dwDisplayType ==2))  tmpHostName=netresource->lpRemoteName;
    else 
    {
    NetResource_List.AddTail(*netresource); 
    continue; 
    }  if(strncmp(tmpHostName,"\\\\",2)==0) tmpHostName+=2;  //去掉\\符号

    struct hostent *host=gethostbyname(tmpHostName);      //获取远程主机信息
    if(!host) continue;
    struct in_addr *ptr=(struct in_addr*)host->h_addr_list[0];  //利用这个宏获取分段IP

    /*处理主机信息结构,然后添加到列表中*/
    strcpy(hm.hostname ,tmpHostName);
    hm.hostname_len =strlen(tmpHostName) ;
    hm.hostaddr[0]=ptr->S_un.S_un_b.s_b1 ;
    hm.hostaddr[1]=ptr->S_un.S_un_b.s_b2 ;
    hm.hostaddr[2]=ptr->S_un.S_un_b.s_b3 ;
    hm.hostaddr[3]=ptr->S_un.S_un_b.s_b4 ;
    hm.online =1;
    memset(hm.wgname,0,256);
    hm.wgname_len =0;

    WPARAM wParam=(WPARAM) (&hm);
    SendMessage(hWnd,WM_GET_ONE_HOST,wParam,0); hostmsg_list.AddTail(hm);    //添加到列表
    //}
    } int vCount=NetResource_List.GetCount();
    if(vCount>0)
    {
    POSITION pos=NetResource_List.GetHeadPosition();
    for(int i=0;i<vCount;i++)
    {
    NETRESOURCE vNewResource=NetResource_List.GetNext(pos);
    Enum_NetWork(&vNewResource,hWnd);
    }
    }
    }//获取下一个主机信息,发生错误返回-1,否则返回列表的索引号
    int LANsource::GetNextHost(char *HostName,int *HostName_len,char *HostAddr,int *Online)
    {
    int nCount=hostmsg_list.GetCount();    //获取列表长度 if(nCount!=0)
    {
    if(nFlag>=nCount) nFlag=0;         //如果循环过度,则折回
    if(nFlag==0) pos=hostmsg_list.GetHeadPosition();     //获得POSITION /*获取主机信息结构*/
    hostmsg tmpHost=hostmsg_list.GetNext(pos);
    nFlag++; strcpy(HostName,tmpHost.hostname);
    *HostName_len=tmpHost.hostname_len;
    *Online=tmpHost.online ; char s0[4],s1[4],s2[4],s3[4];
    _itoa(tmpHost.hostaddr[0],s0,10);
    _itoa(tmpHost.hostaddr[1],s1,10);
    _itoa(tmpHost.hostaddr[2],s2,10);
    _itoa(tmpHost.hostaddr[3],s3,10);
    strcpy(HostAddr,s0);
    strcat(HostAddr,".");
    strcat(HostAddr,s1);
    strcat(HostAddr,".");
    strcat(HostAddr,s2);
    strcat(HostAddr,".");
    strcat(HostAddr,s3);
    return nFlag;
    }
    return -1;
    } //根据指定的IP地址,扫描主机名称
    int LANsource::ScanHostByAddr(char *HostAddrs,char *HostAddre,HWND hWnd)
    {
    int vResult;
    int vsip[4]={0,0,0,0};
    int veip[4]={0,0,0,0};
    vResult=ParasIP(HostAddrs,HostAddre,vsip,veip);    //将字符串解析为数组

    if(vResult==ERROR_ADDRESS) return ERROR_ADDRESS;//地址错误,返回错误
    return GetHostByAddr(vsip,veip,vResult,hWnd);    //实际的扫描程序

    }
      

  7.   

    //确定IP地址的类型,并将IP地址串解析为四维的整数数组
    int LANsource::ParasIP(char *Start_IP,char *End_IP,int *int_startip,int *int_endip)
    {
    char s_startip[16];
    char s_endip[16];
    strcpy(s_startip,Start_IP);
    strcpy(s_endip,End_IP); int Index,vResult;  //整数数组的索引
    char *tmp,*tmp1; //处理第一个IP地址:
    Index=0;
    tmp=s_startip;
    tmp1=s_startip; while(Index<4)
    {
    if(*tmp1=='.')
    {
    *tmp1=NULL;
    int_startip[Index]=atoi(tmp);
    Index++;
    tmp1++;
    tmp=tmp1;
    }
    else if(*tmp1==NULL)
    {
    int_startip[Index]=atoi(tmp);
    break;
    }
    else tmp1++;
    }

    //处理第二个IP地址
    Index=0;
    tmp=s_endip;
    tmp1=s_endip; while(Index<4)
    {
    if(*tmp1=='.')
    {
    *tmp1=NULL;
    int_endip[Index]=atoi(tmp);
    Index++;
    tmp1++;
    tmp=tmp1;
    }
    else if(*tmp1==NULL)
    {
    int_endip[Index]=atoi(tmp);
    break;
    }
    else tmp1++;
    }

    //判断地址类型
    //地址是否合法,又没有小于0或者大于254的,特别是首位、末位不能是0
    if(!int_startip[0] || !int_startip[3] || 
    !int_endip[0] || !int_endip[3] ) return ERROR_ADDRESS; for(Index=0;Index<4;Index++)
    {
    if(int_startip[Index]<0 || int_startip[Index]>254 || 
    int_endip[Index]<0 || int_endip[Index]>254) return ERROR_ADDRESS;
    } //然后判断地址类型,根据类型判断前几位应该相等
    if((int_startip[0]-128)<0) vResult=A_ADDRESS;
    else if((int_startip[0]-192)<0 )vResult=B_ADDRESS;
    else if((int_startip[0]-224)<0 )vResult=C_ADDRESS;
    else vResult=OTHER_ADDRESS;

    int vExchange=0;//置为1则需要交换数组 switch(vResult)
    {
    case A_ADDRESS:
    if(int_startip[0]-int_endip[0]!=0) return ERROR_ADDRESS;  //首位不相等
    if((int_startip[1]*1000000+int_startip[2]*1000+int_startip[3])>
    (int_endip[1]*1000000+int_endip[2]*1000+int_endip[3])) vExchange=1;
    break;
    case B_ADDRESS:
    if(int_startip[0]-int_endip[0]!=0 || 
    int_startip[1]-int_endip[1]!=0) return ERROR_ADDRESS;  //前两位不相等
    if((int_startip[2]*1000+int_startip[3])>
    (int_endip[2]*1000+int_endip[3])) vExchange=1;
    break;
    case C_ADDRESS:
    if(int_startip[0]-int_endip[0]!=0 || 
    int_startip[1]-int_endip[1]!=0 ||
    int_startip[2]-int_endip[2]!=0) return ERROR_ADDRESS; //前三位不相等
    if(int_startip[3]>int_endip[3]) vExchange=1;
    break;
    case OTHER_ADDRESS:
    break;
    }
    //最后判断两个地址哪个比较大,如果第一个大于第二个,则进行处理。
    if(vExchange)
    {
    int vMid;
    for(Index=0;Index<4;Index++)
    {
    vMid=int_startip[Index];
    int_startip[Index]=int_endip[Index];
    int_endip[Index]=vMid;
    }
    }
    return vResult;
    }//根据获取的主机信息,组合为hostmg,然后发送消息
    void LANsource::GetHostMsg(struct hostent *host,int *startIP,HWND hWnd)
    {
    hostmsg hm;
    if(host)
    {
    strcpy(hm.hostname,host->h_name);
    hm.hostname_len =strlen(host->h_name);
    hm.hostaddr[0]=startIP[0];
    hm.hostaddr[1]=startIP[1];
    hm.hostaddr[2]=startIP[2];
    hm.hostaddr[3]=startIP[3];
    hm.wgname_len =0;
    memset(hm.wgname,0,256);
    hm.online =1;
    }
    else
    {
    if(startIP[0]>0)
    strcpy(hm.hostname,"该IP未占用");
    else
    strcpy(hm.hostname,"网络中没有这个主机");
    hm.hostname_len =strlen(hm.hostname);
    hm.hostaddr[0]=startIP[0];
    hm.hostaddr[1]=startIP[1];
    hm.hostaddr[2]=startIP[2];
    hm.hostaddr[3]=startIP[3];
    hm.wgname_len =0;
    memset(hm.wgname,0,256);
    hm.online =0;
    }
    SendMessage(hWnd,WM_GET_ONE_HOST_BYADDR,(WPARAM)(&hm),0);
    }//根据主机名获取主机信息
    int LANsource::ScanHostByName(char *HostName,HWND hWnd)
    {
    struct hostent *host;
    int vIP[4]={0,0,0,0};
    int vResult=0; host=gethostbyname(HostName);
    if(host)
    {
    struct in_addr *ptr=(struct in_addr *)host->h_addr_list[0];
    vIP[0]=ptr->S_un.S_un_b.s_b1 ;
    vIP[1]=ptr->S_un.S_un_b.s_b2 ;
    vIP[2]=ptr->S_un.S_un_b.s_b3 ;
    vIP[3]=ptr->S_un.S_un_b.s_b4 ;
    vResult=1;
    }
    GetHostMsg(host,vIP,hWnd);
    return vResult;
    }
    //实际根据IP地址获取主机信息
    int LANsource::GetHostByAddr(int *startIP,int *endIP,int IPType,HWND hWnd)
    {
    in_addr s_IP;
    struct hostent *host;
    int i; switch(IPType)
    {
    case A_ADDRESS:  //此类地址在以后扩展的时候处理
    break;
    case B_ADDRESS:   //此类地址在以后扩展的时候处理
    //定义两个变量i,v,分别指向开始和结束IP的第三个IP值
    //从第三个IP值建立循环,直到结束IP
    //如果开始和结束IP的第三个IP相等,则第四个IP值从开始循环到结束
    //否则,如果i=startip[2],则从startIP[4]循环至254
    //否则,如果v!=startip[2],则从1循环到254
    //否则,如果v==startip[2].则从1循环到endip[4]
    break;
    case C_ADDRESS:
    for(;startIP[3]<=endIP[3];startIP[3]++)
    {
    s_IP.S_un.S_addr = inet_addr(fmtIPString(startIP));
    host=gethostbyaddr((const char*)&s_IP,sizeof(s_IP),AF_INET);
    GetHostMsg(host,startIP,hWnd);
    }
    break;
    }
    return IPType;
    }//根据数组组合成字符串
    char *LANsource::fmtIPString(int *IP)
    {
    char *vResult=new char(16);
    char *tmp=new char[4]; _itoa(IP[0],vResult,10);
    strcat(vResult,"."); _itoa(IP[1],tmp,10);
    strcat(vResult,tmp);
    strcat(vResult,"."); _itoa(IP[2],tmp,10);
    strcat(vResult,tmp);
    strcat(vResult,"."); _itoa(IP[3],tmp,10);
    strcat(vResult,tmp); return vResult;
    }