freeeyes 发表于 2011-10-26 17:26:35

ACE下的PING功能实现

本帖最后由 freeeyes 于 2011-10-26 17:32 编辑

虽说ping被很多服务器的防火墙默认拒绝,不过,做一个简单的ping命令有时候还是有所必要的。用ACE实现一个ping非常简单,不超过40行代码即可实现。查了一下网上的ACE的ping代码,似乎都多少有点问题。这里放一个可以运行的。供大家参考抛砖。
首先,需要引用一个ACE_Ping_Socket,它继承来自ACE_ICMP_Socket。ping需要远端提供ICMP支持。
代码如下:
#include "ace/OS_main.h"
#include "ace/INET_Addr.h"
#include "ace/Log_Msg.h"
#include "ace/Time_Value.h"
#include "ace/OS_NS_sys_time.h"
#include "ace/OS_NS_unistd.h"
#include "ace/Ping_Socket.h"

class CPing
{
public:
      CPing(void);
      ~CPing(void);

      bool PingHost(const char* pServerIP, int nTimeout, int& nTimeCost);

private:
      ACE_Ping_Socket m_Ping;
};

这里提供一个方法。PingHost()
pServerIP是你要ping的远程服务器地址。
nTimeout是的ping命令超时的时间。(不能无限制等下去)
nTimeCost返回一个时间消耗,单位是毫秒。
其实对于ping,我们知道是否能ping通,时间消耗多少,往往就够了。
好了。来看看实现代码。
#include "Ping.h"

CPing::CPing(void)
{
}

CPing::~CPing(void)
{
}

bool CPing::PingHost(const char* pServerIP, int nTimeout, int& nTimeCost)
{
      //发送的测试数据
      ACE_INET_Addr addrRemote;
      int nErr = addrRemote.set("0", pServerIP);
      if(nErr != 0)
      {
                ACE_DEBUG((LM_ERROR, "set_address error[%d].\n", errno));
                return false;
      }

      nErr = m_Ping.open(ACE_INET_Addr::sap_any);
      if(nErr != 0)
      {
                ACE_DEBUG((LM_ERROR, "open error[%d].\n", errno));
                return false;
      }

      ACE_Time_Value tvTimeBegin;
      ACE_Time_Value tvTimeEnd;
      ACE_Time_Value tvRecvCost;

      ACE_Time_Value tvTimeout(nTimeout, 0);
      tvTimeBegin = ACE_OS::gettimeofday();
      int nmcData = m_Ping.make_echo_check(addrRemote, false, &tvTimeout);
      if(nmcData != 0)
      {
                ACE_DEBUG((LM_ERROR, "make_echo_check error[%d].\n", errno));
                m_Ping.close();
                return false;
      }
      tvTimeEnd = ACE_OS::gettimeofday();

      tvRecvCost = tvTimeEnd - tvTimeBegin;
      nTimeCost = (int)tvRecvCost.msec();

      m_Ping.close();

      return true;
}


这里解释一下,谷歌了一下一些关于用这个类的问题,很多人不知道为什么ping会返回-1.
其实解决这类问题的关键点是
m_Ping.open(ACE_INET_Addr::sap_any);
好了,以上代码并不难理解。
自己测试一下上述代码吧。
int main(int argc, char* argv[])
{
      int nTimeCost = 0;
      CPing objPing;
      for(int i = 0; i < 5; i++)
      {
                char* pIP = {"123.103.14.237"};
                if(true == objPing.PingHost(pIP, 2, nTimeCost))
                {
                        ACE_DEBUG((LM_INFO, "IP=[%s] TimeCost=[%d].\n", pIP, nTimeCost));
                }
                ACE_Time_Value tvSleep(1, 0);
                ACE_OS::sleep(tvSleep);
      }
      getchar();

      return 0;
}


呵呵,123.103.14.237是网易的IP,你可以实际ping一下,对比一下两个数值。
这里多一句嘴,在ACE的ping类里面提供两个函数,一个是我上述用到的make_echo_check(),这个协议是发送一个ICMP数据包来回(一个send,一个recv)后的时间,另外还有一个接口是send_echo_check(),这个方法是只发送一个ICMP,并不接收回应,只要发送成功即返回,可以用于查看某一个IP是否有效,而不在乎响应时间的应用。你可以在这段代码中稍微改一下就可以了。
好了,呵呵,以上代码在我的VS2005 + ACE6.0 + WinXP下测试通过。最近项目比较忙,呵呵,这两天把0.82上传上来,增加了一些给力的功能。

泡菜丝丝 发表于 2011-10-27 10:04:25

期待给力的新功能:lol
页: [1]
查看完整版本: ACE下的PING功能实现