形如在SQL中,在使用导入导出向导的时候SQL会把局域网中所有的可用SQL服务器列出,即查找局域网内所有开放1433端口的机器,现在想实现这个功能,如何实现?请教各位。

解决方案 »

  1.   

    主要思想是:广播数据报,如果有回复,则进行解析并得出结果。或者通过建立socket连接的成功与否来判断,但是不知道Java如何实现,如new socket("192.168.1."+i,8001); 
      

  2.   

    先获取当前的IP,然后根据子网掩码得出所有子网内的IP范围。 然后就是尝试连接。好一点,不光TCP,还要看udp等
      

  3.   

    利用socket编程发送一个广播,根据响应获取相应的IP地址
      

  4.   


    头文件: 
    /* 
    扫描局域网活动主机端口类 LanActiveHost 
    */ 
    #include <winsock.h> 
    #pragma comment(lib, "ws2_32.lib") class LanActiveHost 

    public:        
                //建议线程 不超过200  毫秒超时设置 最好大于1秒  小于1秒结果不可靠 
                    LanActiveHost(short _MaxThread,short _Port,DWORD _TimeOutValue); 
                    ~LanActiveHost(); 
      BOOL          GetHostIP(); 
      BOOL          GetIP3(); 
      BOOL          InitIPList(); 
      static BOOL  Try3_ConnSelect(fd_set r,struct timeval tm); 
      static BOOL  Try3_SendSelect(fd_set r,struct timeval tm); 
      static BOOL  Try3_RecvSelect(fd_set r,struct timeval tm);   static BOOL  CFG_DP();  
      static BOOL  Chk_ServMsg(int id); 
      static BOOL  SetMsgRec(BOOL flag,int id);   static DWORD  WINAPI DoScanPort(LPVOID lpParam); 
      static DWORD  WINAPI StartScan(LPVOID lpParam); 
      static BOOL  GetServerMSG(char ServerMsg[256][34]); 
      BOOL          StartListServer(); 
      BOOL          EndListServer(); 
      BOOL          Get_IPIndex(char ip[256][16],char index[256]); 
      
      
    private: 
      HANDLE        Handle;          //父线程句柄 
      static DWORD  TimeOutValue ;    //连接超时时间,以ms计 
      static short  ThreadCount;      //当前正在扫描的进程数  
      static short  Port;            //端口 
      static char  IP[256][16];      //局域网IP列表 
      static char  Index[256];      //局域网活动服务器 是1  否0 
      
      static char  send_str[5];      //发送数据缓存 
      static char  recv_str[256][40];    //接收数据缓存 
      static int    send_len;          
      static int    recv_len; 
      
      static char  RecvMsg[256][34]; //收到每个主机返回的信息 32 GSP 1 Num   short        MaxThread;        //最大允许的扫描线程数,不宜大于200 
      char          HostIP[16];      //本机IP 
      char          IP3[16];          //IP前3段 
    };  用c++搞过,但没有用java搞过
      

  5.   


    实现文件 .cpp 
    #include "LanHost.h" DWORD LanActiveHost::TimeOutValue ;  
    short LanActiveHost::ThreadCount  ;      
    short LanActiveHost::Port        ; 
    char  LanActiveHost::IP[256][16]  ; 
    char  LanActiveHost::Index[256]  ;  
    char  LanActiveHost::send_str[5]  ; 
    char  LanActiveHost::recv_str[256][40] ; 
    int  LanActiveHost::send_len    ; 
    int  LanActiveHost::recv_len    ;  
    char  LanActiveHost::RecvMsg[256][34];  //构造函数 
    LanActiveHost::LanActiveHost(short _MaxThread,short _Port,DWORD _TimeOutValue) 

    MaxThread    =  _MaxThread; 
    Port        =  _Port; 
    TimeOutValue =  _TimeOutValue; 
    //配置数据协议 
    LanActiveHost::CFG_DP();  

    //析构函数 
    LanActiveHost::~LanActiveHost() 


    //获取本机IP地址 
    BOOL LanActiveHost::GetHostIP() 
    {  
      char  HostName[128]; 
      LPSTR  Addr; 
      struct hostent FAR *HostEnt; 
      
      //获取主机名称 -1错误  0成功 
      if( gethostname(HostName, sizeof(HostName)) == SOCKET_ERROR ) 
      return FALSE;   //获取名称结构 
      HostEnt  = gethostbyname (HostName);   //主机名称可能有多个IP地址 在此默认第一个地址 
      Addr      = HostEnt->h_addr_list[0];   //IP -> XXX.XXX.XXX.XXX 
      if (!Addr) 
      return FALSE; 
      else 
      { 
      struct in_addr  inAddr; 
      memmove (&inAddr, Addr, 4); 
      strcpy(HostIP,inet_ntoa (inAddr)); 
      } 
      return TRUE; 

    // 得到IP前3段 XXX.XXX.XXX.XXX -> XXX.XXX.XXX. --------------------- 
    BOOL LanActiveHost::GetIP3() 

      int i=0,j=0; 
      while(1) 
      { 
      IP3[i]=HostIP[i]; 
      if(HostIP[i]=='.') 
        j++; 
      if(j==3) 
        break; 
      i++; 
      } 
      IP3[i+1]='\0'; 
      return TRUE; 

    //初始化局域网 IP列表 
    BOOL LanActiveHost::InitIPList() 

      int  i; 
      char IP4[4];   //获取本机IP 
      if( !LanActiveHost::GetHostIP() ) 
      return FALSE; 
      //获取IP前三段 
      LanActiveHost::GetIP3();   //初始化局域网IP 
      for(i=1;i <=255;i++) 
      { 
      strcpy(IP[i],IP3); 
      itoa(i,IP4,10); 
      strcat(IP[i],IP4); 
      IP[i][strlen(IP[i])]='\0'; 
      } 
      return TRUE; 
    } //配置网络数据协议 
    BOOL LanActiveHost::CFG_DP() 

    send_str[0] = 'A'; 
    send_str[1] = 'M'; 
    send_str[2] = CMSG_See; 
    send_str[3] = '\0'; 
    send_len    = 5; 
    recv_len    = 40; 
    return TRUE; 
    } //检查接收内容是否正确 
    BOOL LanActiveHost::Chk_ServMsg(int id) 

    if( recv_str[id][0]=='A' && recv_str[id][1]=='M' && (unsigned char)recv_str[id][2]==SMSG_Server ) 
    return TRUE; 
    else 
    return FALSE; 

    //设置接收信息记录 
    BOOL LanActiveHost::SetMsgRec(BOOL flag,int id) 

      if(flag==TRUE) 
      { 
        //记录 
        Index[id]=1; 
    DataCopy(recv_str[id]+3,RecvMsg[id],33); 
    RecvMsg[id][33]='\0'; 
      } 
      else 
      { 
        //清零 
        Index[id]=0; 
        memset(RecvMsg[id],0,sizeof(RecvMsg[id])); 
      } 
      return TRUE; 

    //连接监听尝试3次 成功返回1  失败返回0 
    BOOL LanActiveHost::Try3_ConnSelect(fd_set r,struct timeval tm) 

      int num = 1;   //尝试第一1次 
      int ret = select(0, NULL,  &r,  NULL,  &tm);   //若失败再尝试2次 
      while( ret <=0 && num <3 ) 
      { 
      ret = select(0, NULL, &r, NULL, &tm); 
      num++; 
      }   //返回结果 
      if( ret>0 ) 
      return TRUE; 
      else 
      return FALSE; 
    } //发送监听尝试3次 成功返回1  失败返回0 
    BOOL LanActiveHost::Try3_SendSelect(fd_set r,struct timeval tm) 

      int num = 1;   //尝试第一1次 
      int ret = select(0,  NULL,  &r,  NULL,  &tm);   //若失败再尝试2次 
      while( ret <=0 && num <3 ) 
      { 
      ret = select(0, NULL, &r, NULL, &tm); 
      num++; 
      }   //返回结果 
      if( ret>0 ) 
      return TRUE; 
      else 
      return FALSE; 
    } //接收监听尝试3次 成功返回1  失败返回0 
    BOOL LanActiveHost::Try3_RecvSelect(fd_set r,struct timeval tm) 

      int num = 1;   //尝试第一1次 
      int ret = select(0,  &r,  NULL,  NULL,  &tm);   //若失败再尝试2次 
      while( ret <=0 && num <3 ) 
      { 
      ret = select(0,  &r,  NULL, NULL,  &tm); 
      num++; 
      }   //返回结果 
      if( ret>0 ) 
      return TRUE; 
      else 
      return FALSE; 
    } //对外接口 提供接收的服务器信息 
    BOOL LanActiveHost::GetServerMSG(char Msg[256][34]) 

    int i; 
    //Msg清零 
    memset(Msg,0,sizeof(Msg)); //如果是服务器 提交信息 
        for(i=1;i <=255;i++) 
        if(Index[i]==1) 
    DataCopy(RecvMsg[i],Msg[i],33); 
    return TRUE; 

    //扫描局域网存活主机 子线程函数 
    DWORD WINAPI LanActiveHost::DoScanPort(LPVOID lpParam) 

    int  id = (int)lpParam; //创建套接字 
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0); //创建套接字失败 
    if(sock == INVALID_SOCKET) 

      ThreadCount --; 
          return 0; 
    } //创建套接字成功 
    else 

          //强制关闭,不经历TIME_WAIT过程 
          BOOL bDontLinger  =  FALSE;    
          setsockopt(sock,SOL_SOCKET,SO_DONTLINGER,(const  char*)&bDontLinger,sizeof(BOOL)); 
      //设置非阻塞socket 
      unsigned long flag = 1; 
      int ret = ioctlsocket(sock, FIONBIO, (unsigned  long*)&flag);   //设置失败 
      if( ret == SOCKET_ERROR ) 
          { 
      ThreadCount --; 
          return 0; 
      }   //主机地址 
      sockaddr_in Addr; 
      Addr.sin_family = AF_INET; 
      Addr.sin_port = htons(Port); 
      Addr.sin_addr.S_un.S_addr =inet_addr(IP[id]);   //连接主机 
      connect(sock, (sockaddr*)&Addr, sizeof(Addr));   //超时设置 
      struct fd_set mask; 
      FD_ZERO(&mask); 
      FD_SET(sock, &mask); 
      struct timeval timeout; 
      timeout.tv_sec  = TimeOutValue/1000;        //秒 
      timeout.tv_usec = (TimeOutValue%1000)*1000; //微秒    //连接成功 
      if( LanActiveHost::Try3_ConnSelect(mask,timeout) == TRUE )       //监听发送 
          if( LanActiveHost::Try3_SendSelect(mask,timeout) == TRUE ) 
          send(sock,send_str,send_len,0);   strcpy(recv_str[id],"NULL\0");   //监听接收 
          if( LanActiveHost::Try3_RecvSelect(mask,timeout) == TRUE ) 
          recv(sock,recv_str[id],recv_len,0);   //接收内容正确 
      if( LanActiveHost::Chk_ServMsg(id) == TRUE ) 
      LanActiveHost::SetMsgRec(TRUE,id); 
      else 
          LanActiveHost::SetMsgRec(FALSE,id); 
      //断开连接 
      shutdown(sock,0); 
      closesocket(sock); 
      sock = -1; 

          
    ThreadCount --; 
    return 1; 

    //扫描局域网存活主机 父线程函数 
    DWORD WINAPI LanActiveHost::StartScan(LPVOID lpParam) 

        DWORD ThreadId; 
        unsigned short i;     for(i=1; i <=255; i++) 
        if (CreateThread(NULL, 0,LanActiveHost::DoScanPort, (LPVOID)i, 0, &ThreadId) != NULL) 
        ThreadCount ++;     //等待所有子线程退出 
        while (ThreadCount > 0) 
        Sleep(20); 
        
    return 1; 

    //扫描局域网存活主机 
    BOOL LanActiveHost::StartListServer() 

        //初始化局域网 IP列表与索引  
        if( !LanActiveHost::InitIPList() ) 
        return FALSE; //线程计数器初始化 
        ThreadCount  = 0;     //创建扫描父线程,该线程包含多个子线程 
        DWORD ThreadId; 
        Handle = CreateThread(NULL, 0,LanActiveHost::StartScan, NULL, 0, &ThreadId);     //线程创建成功 
        if( Handle )  
            return TRUE;     //线程创建失败 
        else          
            return FALSE; 

    //等待扫描线程安全退出 
    BOOL LanActiveHost::EndListServer() 

    //等待子线程退出 
        while( ThreadCount>0 ) 
    Sleep(20); 
    //等待父线程退出 
    Sleep(100); 
        return TRUE; 

    //外部接口提供服务器IP列表 存活索引 
    BOOL LanActiveHost::Get_IPIndex(char ip_list[256][16],char ip_index[256]) 

    int i; 
    for(i=1;i <=255;i++) 
    if(Index[i]==1) 

      strcpy(ip_list[i],IP[i]); 
      ip_index[i] = Index[i]; 

    else 
      ip_index[i] = 0; 
    return TRUE; 
      

  6.   


    主机端 应答 
    头文件 
    class LanServer 

    public: 
                      //客户端最大15 最小1 
                      LanServer(int _Port,int _Max_Client,int _TimeOut,int _HeartTimeOut); 
                      ~LanServer(); 
        BOOL        InitServer(); 
        BOOL        Listen(short blockbuf); 
        BOOL        GetPlayer(int id); 
        static BOOL  Try3_SendSelect(fd_set r,struct timeval tm); 
        static BOOL  Try3_RecvSelect(fd_set r,struct timeval tm); 
    //    BOOL        ClientMSG_PRC(int id,char recv[],PLAYER_DATA player_data); 
        BOOL        EndSock(int id); 
        static UINT  ServerThread(LPVOID p); 
        static BOOL  GetFreeSock(int &id,int &num); 
    private:    
        int                  Port; 
        int                  PlayerPos[16]; 
        static int            TimeOut; 
        static int            HeartTimeOut; 
        static SOCKET        Socket[17]; 
        static sockaddr_in    Addr;  
        static int            AddrLen; 
        static int            Max_Client; 
    }; 实现文件 
    //主机端 
    #include "Server.h" int            LanServer::TimeOut; 
    int            LanServer::HeartTimeOut;        
    int            LanServer::Max_Client; 
    int            LanServer::AddrLen=0; 
    SOCKET        LanServer::Socket[17]; 
    sockaddr_in    LanServer::Addr;  char StrGet[300]; 
    //构造函数 
    LanServer::LanServer(int _Port,int _Max_Client,int _TimeOut,int _HeartTimeOut) 

    Port        =  _Port; 
    Max_Client  =  _Max_Client; 
    TimeOut      =  _TimeOut; 
    HeartTimeOut =  _HeartTimeOut; 
    } //析构函数 
    LanServer::~LanServer() 

    LanServer::EndSock(-1); 
    } //初始化服务器 绑定端口 
    BOOL LanServer::InitServer() 

      int i;   //所有套接字初始化 
      for (i=0;i <=Max_Client+1;i++) 
      Socket[i] = -1;   //设定地址 
      Addr.sin_addr.s_addr= htonl(INADDR_ANY);                  
      Addr.sin_family    = AF_INET; 
      Addr.sin_port      = htons(Port); 
      AddrLen            = sizeof(Addr);   //创建socket 
      Socket[0]          =socket(AF_INET,SOCK_STREAM,0);   //创建socket失败 
      if( Socket[0] == INVALID_SOCKET ) 
      return FALSE;   //强制关闭,不经历TIME_WAIT过程 
      BOOL bDontLinger  =  FALSE;    
      setsockopt(Socket[0],SOL_SOCKET,SO_DONTLINGER,(const  char*)&bDontLinger,sizeof(BOOL)); 
      
      //绑定成功 
      if ( bind(Socket[0],(sockaddr*)&Addr,sizeof(Addr)) ==0)  
      return TRUE;   //绑定失败 
      else                                                      
      return FALSE; 
    } //开始监听 
    BOOL  LanServer::Listen(short blockbuf) 

    listen(Socket[0],blockbuf); 
    return TRUE; 
    } //获取空闲套接字 
    BOOL  LanServer::GetFreeSock(int &id,int &num) 

          int i; 
          id  =  0; 
          num =  0; 
          for(i=Max_Client+1;i>=1;i--) 
          if (Socket[i]==-1) 
          { 
        id  = i; 
      num ++ ; 
          } 
          return TRUE; 

    //终止连接 
    BOOL LanServer::EndSock(int id) 

      int i;   //非法操作 
      if(id <-1 || id>15) 
      return FALSE;   //若索引为0-15 则终止该索引对应的套接字 
      if(id>=0 && Socket[id]!=-1) 
      { 
      closesocket(Socket[id]); 
      Socket[id]=-1; 
      }   //若索引为 -1 则终止所有 套接字 
      else if(id==-1) 
      for(i=0;i <=Max_Client;i++) 
      { 
      closesocket(Socket[id]); 
      Socket[id]=-1; 
      }   return TRUE; 
    } //尝试3次接收监听 成功返回1  失败返回0 
    BOOL LanServer::Try3_RecvSelect(fd_set r,struct timeval tm) 

      int num = 1;   //尝试第一1次 
      int ret = select(0,  &r,  NULL,  NULL,  &tm);   //若失败再尝试2次 
      while( ret <=0 && num <3 ) 
      { 
      ret = select(0, &r, NULL, NULL, &tm); 
      num++; 
      }   //返回结果 
      if( ret>0 ) 
      return TRUE; 
      else 
      return FALSE; 
    } //尝试3次接收监听 成功返回1  失败返回0 
    BOOL LanServer::Try3_SendSelect(fd_set r,struct timeval tm) 

      int num = 1;   //尝试第一1次 
      int ret = select(0,  NULL,  &r,  NULL,  &tm);   //若失败再尝试2次 
      while( ret <=0 && num <3 ) 
      { 
      ret = select(0,  NULL,  &r,  NULL,  &tm); 
      num++; 
      }   //返回结果 
      if( ret>0 ) 
      return TRUE; 
      else 
      return FALSE; 

    //服务器工作线程 
    UINT LanServer::ServerThread(LPVOID p) 
    {  
        int  id,num;     //获得客户端数量 
        LanServer::GetFreeSock(id,num);     while( num==1 )        
        { 
          //终止线程 
          Sleep(20); 
          LanServer::GetFreeSock(id,num); 
        }     //接受连接 
        Socket[id]=accept(Socket[0],(sockaddr*)&Addr,&AddrLen);     //强制关闭,不经历TIME_WAIT过程 
        BOOL bDontLinger  =  FALSE;    
        setsockopt(Socket[id],SOL_SOCKET,SO_DONTLINGER,(const  char*)&bDontLinger,sizeof(BOOL));     //开启新线程 
        AfxBeginThread(LanServer::ServerThread,0);     CAMatchDlg *dlg= (CAMatchDlg *)AfxGetApp()->GetMainWnd();     if ( Socket[id]!=INVALID_SOCKET ) //连接正确 
        { 
          //设置非阻塞方式 
          unsigned  long  ul  =  1;  
          ioctlsocket(Socket[id],  FIONBIO,  (unsigned  long*)&ul);       fd_set r; 
          FD_ZERO(&r); 
          FD_SET(Socket[id], &r);       struct timeval tm; 
          tm.tv_sec  = TimeOut/1000 ; 
          tm.tv_usec = (TimeOut%1000)*1000; 
          
          while(1) 
          { 
              //尝试3次接收监听 
              if( LanServer::Try3_RecvSelect(r,tm) == FALSE ) 
              break;           //接收数据 
              if( recv(Socket[id],StrGet,230,0) <=0 ) 
              break;           //处理接收数据 
              ClientMSG_Processing(id,msg_data.StrGet,client_data);           //处理发送数据 
              int Ret = ClientMSG_Put(id, msg_data.StrGet, am_skin, client_data, am_game, msg_data.StrPut); 
        
              //发送数据 
              if( (Ret==2 || Ret==3) && LanServer::Try3_SendSelect(r,tm) == TRUE )  
              { 
                if( send(Socket[id], msg_data.StrPut, 50,0) <=0 ) 
                send(Socket[id], msg_data.StrPut, 50,0); 
              } 
              //关闭套接字 
              if( Ret==0 || Ret==2 ) 
              break; 
          } 
        } 
        closesocket(Socket[id]); 
        Socket[id]=-1; 
        ::AfxMessageBox("服务器断开",0,0); 
        
        //终止线程 
        AfxEndThread(0); 
        return 0; 

    //处理客户端信息  TRUE 保持    FALSE 断开 
    BOOL  LanServer::ClientMSG_PRC(int id,char recv[],PLAYER_DATA player_data,char Msg[]) 

      //非法数据不处理 
      if( !(recv[0]=='A' && recv[1]=='M') ) 
      return TRUE;   //依据协议 为即将发送的数据 添加数据头 
      memset(Msg,0,sizeof(Msg)); 
      Msg[0]='A'; 
      Msg[1]='M';   //获取消息类型 
      int MSG_ID = (unsigned char)recv[2];   //依据类型处理 
      switch( MSG_ID ) 
      {  
        //查询服务器信息  
        case CMSG_See: 
        { 
          Msg[2] = SMSG_Server; 
          DataCopy(player_data.GSP,Msg+3,32); 
          int i,num=0; 
          for(i=0;i <16;i++) 
          if( client_data.Flag[i] ) 
            num++; 
          Msg[35] = num; 
          Msg[36] = '\0'; 
          
          return TRUE; 
        } 
        //申请加入服务器 
        case CMSG_Ask: 
        { 
            //拷贝玩家名称 
            char sname[17]; 
            DataCopy(recv+3,sname,16);         //增加玩家信息 
            AddPlayer(id, sname, player_data.Live, player_data.Flag, player_data.Name[id]); 
            return TRUE; 
        } 
      
        //准备完毕 等待开始 
        case CMSG_Ready: 
        {  
            //拷贝初始化棋盘数据 
            DataCopy(recv+3, player_data.Init[id], 216); 
            return TRUE; 
        }     //游戏进度 
        case CMSG_Game: 
        { 
              //数据包次序 
              int PackID = (unsigned char)recv[3];           //对比次序 判断是否丢失严重  100 210 321 432 543 
              if( PackID - (unsigned char)palyer_data.PID[id] >= 3 ) 
              return FALSE;           //更新数据包次序 
              palyer_data.PID[id] = PackID;           //拷贝销毁点 与 交换点 
              DataCopy(recv+4, player_data.SP[id], 3); 
              DataCopy(recv+7, player_data.EP[id], 3); 
              return TRUE; 
        } 
      
        //离开游戏 
        case CMSG_Leave: 
        {      
              //删除玩家信息 
              DeletePlayer(id, player_data.Live, player_data.Flag, player_data.Name[id]); 
              return FALSE; 
        }     //保持信号 
        case CMSG_Keep: 
        { 
              //心跳包计数器 增加 
              player_data.Signal[id] ++; 
              return TRUE; 
        }     //默认不处理 
        default : 
        return TRUE; 
      } 

      

  7.   

    和这个帖子比较相似http://topic.csdn.net/u/20091121/15/1a817a3b-e903-4413-aa19-b280b4bf303a.html