Monthly Archives: March 2011

Poco::Net::ICMPClient

Poco::Net::ICMPClient を紹介します。

ICMPClientTest.cpp

Poco::Net::ICMPClient の static method
  static int ping(SocketAddress& address, IPAddress::Family family, int repeat = 1);
  static int pingIPv4(const std::string& address, int repeat = 1);
 を呼んで、結果(ping の回数分の戻り値が来たかどうか)を表示。
Poco::Net::ICMPClient をインスタンス化し、non-static の method
  int ping(const std::string& address, int repeat = 1) const;
 を呼んで、結果を表示。
 さらに、ICMPClientTest クラスで、pingBegin, pingReply, pingError, pingEnd の Notification イベント
 ハンドラを登録しておいて
  int ping(SocketAddress& address, int repeat = 1) const;
 を呼び、各 Notification の内容と最終結果を表示。

#include <Poco/Format.h>
#include <Poco/Net/ICMPClient.h>
#include <Poco/Net/IPAddress.h>
#include <Poco/Net/ICMPEventArgs.h>
#include <Poco/Delegate.h>
 
#include <string>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
 
const std::string IsOK(bool isOK)
{
	return isOK ? "OK":"NG";
}
 
class ICMPClientTest
{
public:
	ICMPClientTest(	ScopedLogMessage& msg,
			Poco::Net::ICMPClient& client) :
		m_msg		(msg)
	,	m_client	(client)
	{
		m_client.pingBegin += Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onBegin);
		m_client.pingReply += Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onReply);
		m_client.pingError += Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onError);
		m_client.pingEnd   += Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onEnd);
	}
	~ICMPClientTest()
	{
		m_client.pingBegin -= Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onBegin);
		m_client.pingReply -= Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onReply);
		m_client.pingError -= Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onError);
		m_client.pingEnd   -= Poco::Delegate<ICMPClientTest, Poco::Net::ICMPEventArgs>(this, &ICMPClientTest::onEnd);
	}
	int ping(Poco::Net::SocketAddress& address, int repeat) const
	{
		return m_client.ping(address, repeat);
	}
	void onBegin(const void* pSender, Poco::Net::ICMPEventArgs& args)
	{
		m_msg.Message(Poco::format("  Pinging %s [%s] with %d bytes of data:",
				args.hostName(),
				args.hostAddress(),
				args.dataSize()));
	}
	void onReply(const void* pSender, Poco::Net::ICMPEventArgs& args)
	{
		m_msg.Message(Poco::format("   Reply from %s bytes=%d time=%dms TTL=%d",
				args.hostName(),
				args.dataSize(),
				args.replyTime(),
				args.ttl()));
	}
	void onError(const void* pSender, Poco::Net::ICMPEventArgs& args)
	{
		m_msg.Message(Poco::format("   Error: %s ", args.error()));
	}
	void onEnd(const void* pSender, Poco::Net::ICMPEventArgs& args)
	{
		int received = args.received();
		m_msg.Message(Poco::format("  Ping statistics for %s", args.hostName()));
		m_msg.Message(Poco::format("   Packets: Sent=%d, Received=%d, Lost=%d (%3.3f%% loss)",
				args.sent(),
				received,
				args.repetitions() - received,
				100.0 - args.percent()));
		m_msg.Message(Poco::format("   Approximate round trip times: Minimum=%dms, Maximum=%dms, Average=%dms",
				args.minRTT(),
				args.maxRTT(),
				args.avgRTT()));
	}
 
private:
	ScopedLogMessage&		m_msg;
	Poco::Net::ICMPClient&	m_client;
};
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ScopedLogMessage msg("ICMPClientTest ", "start", "end");
 
	try
	{
		const std::string url("poco.roundsquare.net");
		const std::string urlWithPort(url+":80");
		const int numRepeat = 5;
		Poco::Net::SocketAddress socketAddress(urlWithPort);
 
		msg.Message("*** static methods ***");
		msg.Message(Poco::format(" Poco::Net::ICMPClient::ping() - %s",
				IsOK(numRepeat == Poco::Net::ICMPClient::ping(socketAddress, Poco::Net::IPAddress::IPv4, numRepeat))));
		msg.Message(Poco::format(" Poco::Net::ICMPClient::pingIPv4() - %s",
				IsOK(numRepeat == Poco::Net::ICMPClient::pingIPv4(url, numRepeat))));
 
		msg.Message("*** non-static methods ***");
		Poco::Net::ICMPClient icmpClient(Poco::Net::IPAddress::IPv4);
		msg.Message(Poco::format(" Poco::Net::ICMPClient::ping(const std::string& address, int repeat) - %s",
				IsOK(numRepeat == icmpClient.ping(url, numRepeat))));
		ICMPClientTest test(msg, icmpClient);
		msg.Message(" ICMPClientTest::ping() start");
		msg.Message(Poco::format(" ICMPClientTest::ping() - %s",
				IsOK(numRepeat == test.ping(socketAddress, numRepeat))));
	}
	catch(Poco::IOException&)
	{
		msg.Message(" CAUTION: You need to sudo to run this app.");
	}
 
	return 0;
}

Results of execution

・Linux と Mac で実行する時は、sudo してからでないと exception が飛んでしまうので注意。
 (socket() を SOCK_RAW で呼ぶ時には root 特権か CAP_NET_RAW 権限が必要なため)

・On Linux

$ sudo ./ICMPClientTest
[0] ICMPClientTest start
[0] *** static methods ***
[0]  Poco::Net::ICMPClient::ping() - OK
[0]  Poco::Net::ICMPClient::pingIPv4() - OK
[0] *** non-static methods ***
[0]  Poco::Net::ICMPClient::ping(const std::string& address, int repeat) - OK
[0]  ICMPClientTest::ping() start
[0]   Pinging poco.roundsquare.net [210.198.10.133] with 48 bytes of data:
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=32ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]   Ping statistics for poco.roundsquare.net
[0]    Packets: Sent=5, Received=5, Lost=0 (0.000% loss)
[0]    Approximate round trip times: Minimum=31ms, Maximum=32ms, Average=31ms
[0]  ICMPClientTest::ping() - OK
[0] ICMPClientTest end

・On Macintosh OSX 10.6.6

$ sudo ./ICMPClientTest
[0] ICMPClientTest start
[0] *** static methods ***
[0]  Poco::Net::ICMPClient::ping() - OK
[0]  Poco::Net::ICMPClient::pingIPv4() - OK
[0] *** non-static methods ***
[0]  Poco::Net::ICMPClient::ping(const std::string& address, int repeat) - OK
[0]  ICMPClientTest::ping() start
[0]   Pinging mail.roundsquare.net [210.198.10.133] with 48 bytes of data:
[0]    Reply from mail.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from mail.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from mail.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from mail.roundsquare.net bytes=48 time=30ms TTL=128
[0]    Reply from mail.roundsquare.net bytes=48 time=31ms TTL=128
[0]   Ping statistics for mail.roundsquare.net
[0]    Packets: Sent=5, Received=5, Lost=0 (0.000% loss)
[0]    Approximate round trip times: Minimum=30ms, Maximum=31ms, Average=30ms
[0]  ICMPClientTest::ping() - OK
[0] ICMPClientTest end

・On Windows XP sp3

[0] ICMPClientTest start
[0] *** static methods ***
[0]  Poco::Net::ICMPClient::ping() - OK
[0]  Poco::Net::ICMPClient::pingIPv4() - OK
[0] *** non-static methods ***
[0]  Poco::Net::ICMPClient::ping(const std::string& address, int repeat) - OK
[0]  ICMPClientTest::ping() start
[0]   Pinging poco.roundsquare.net [210.198.10.133] with 48 bytes of data:
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=46ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]    Reply from poco.roundsquare.net bytes=48 time=31ms TTL=128
[0]   Ping statistics for poco.roundsquare.net
[0]    Packets: Sent=5, Received=5, Lost=0 (0.000% loss)
[0]    Approximate round trip times: Minimum=31ms, Maximum=46ms, Average=34ms
[0]  ICMPClientTest::ping() - OK
[0] ICMPClientTest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2011年3月20日からのダウンロード数:913

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Powered by POCO Copyright © 2011 Round Square Inc. All rights reserved.