找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4708|回复: 1

ACE下的PING功能实现

[复制链接]
发表于 2011-10-26 17:26:35 | 显示全部楼层 |阅读模式
本帖最后由 freeeyes 于 2011-10-26 17:32 编辑

虽说ping被很多服务器的防火墙默认拒绝,不过,做一个简单的ping命令有时候还是有所必要的。用ACE实现一个ping非常简单,不超过40行代码即可实现。查了一下网上的ACE的ping代码,似乎都多少有点问题。这里放一个可以运行的。供大家参考抛砖。
首先,需要引用一个ACE_Ping_Socket,它继承来自ACE_ICMP_Socket。ping需要远端提供ICMP支持。
代码如下:
  1. #include "ace/OS_main.h"
  2. #include "ace/INET_Addr.h"
  3. #include "ace/Log_Msg.h"
  4. #include "ace/Time_Value.h"
  5. #include "ace/OS_NS_sys_time.h"
  6. #include "ace/OS_NS_unistd.h"
  7. #include "ace/Ping_Socket.h"
  8. class CPing
  9. {
  10. public:
  11.         CPing(void);
  12.         ~CPing(void);
  13.         bool PingHost(const char* pServerIP, int nTimeout, int& nTimeCost);
  14. private:
  15.         ACE_Ping_Socket m_Ping;
  16. };
复制代码

这里提供一个方法。PingHost()
pServerIP是你要ping的远程服务器地址。
nTimeout是的ping命令超时的时间。(不能无限制等下去)
nTimeCost返回一个时间消耗,单位是毫秒。
其实对于ping,我们知道是否能ping通,时间消耗多少,往往就够了。
好了。来看看实现代码。
  1. #include "Ping.h"
  2. CPing::CPing(void)
  3. {
  4. }
  5. CPing::~CPing(void)
  6. {
  7. }
  8. bool CPing::PingHost(const char* pServerIP, int nTimeout, int& nTimeCost)
  9. {
  10.         //发送的测试数据
  11.         ACE_INET_Addr addrRemote;
  12.         int nErr = addrRemote.set("0", pServerIP);
  13.         if(nErr != 0)
  14.         {
  15.                 ACE_DEBUG((LM_ERROR, "[CPing::PingHost]set_address error[%d].\n", errno));
  16.                 return false;
  17.         }
  18.         nErr = m_Ping.open(ACE_INET_Addr::sap_any);
  19.         if(nErr != 0)
  20.         {
  21.                 ACE_DEBUG((LM_ERROR, "[CPing::PingHost]open error[%d].\n", errno));
  22.                 return false;
  23.         }
  24.         ACE_Time_Value tvTimeBegin;
  25.         ACE_Time_Value tvTimeEnd;
  26.         ACE_Time_Value tvRecvCost;
  27.         ACE_Time_Value tvTimeout(nTimeout, 0);
  28.         tvTimeBegin = ACE_OS::gettimeofday();
  29.         int nmcData = m_Ping.make_echo_check(addrRemote, false, &tvTimeout);
  30.         if(nmcData != 0)
  31.         {
  32.                 ACE_DEBUG((LM_ERROR, "[CPing::PingHost]make_echo_check error[%d].\n", errno));
  33.                 m_Ping.close();
  34.                 return false;
  35.         }
  36.         tvTimeEnd = ACE_OS::gettimeofday();
  37.         tvRecvCost = tvTimeEnd - tvTimeBegin;
  38.         nTimeCost = (int)tvRecvCost.msec();
  39.         m_Ping.close();
  40.         return true;
  41. }
复制代码

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

呵呵,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
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-3 10:53 , Processed in 0.022427 second(s), 8 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表