root/trunk/0058_MulticastSocket/MulticastSocketReceiver/MulticastSocketReceiver.cpp

User picture

Author: Setsu

Revision: 348 («Previous)


File Size: 5.56 KB

(February 26, 2011 23:17 UTC) About 1 year ago

0058_MulticastSocket appended.

 
Show/hide line numbers
//
//  MulticastSocketReceiver.cpp
//
//  Created by Setsu on Feb 26, 2011.
//  Copyright 2011 RoundSquare Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

//----------------------------------------
//	include
//----------------------------------------
#include <Poco/Util/ServerApplication.h>
#include <Poco/Task.h>
#include <Poco/TaskManager.h>
#include <Poco/Net/Net.h>
#include <Poco/Net/MulticastSocket.h>
#include <Poco/Net/SocketAddress.h>
#include <Poco/Net/NetworkInterface.h>
#include <Poco/Net/IPAddress.h>
#include <Poco/Format.h>
#include <Poco/NumberParser.h>

#include <string>

//----------------------------------------
//	const
//----------------------------------------
const Poco::Timespan::TimeDiff KWaitUSec(250000);	// 250msec

//----------------------------------------
//	ReceiverTask
//----------------------------------------
class ReceiverTask: public Poco::Task
{
public:
	ReceiverTask(const std::vector<std::string>& args) :	// args[0]: MulticastAddress, args[1]: MulticastPort
		Poco::Task("ReceiverTask")
	,	m_family			(Poco::Net::IPAddress(args[0]).family())
	,	m_port				(Poco::NumberParser::parseUnsigned(args[1]))
	,	m_multicastSocket	(Poco::Net::MulticastSocket(m_family))
	,	m_socketAddres		(args[0], m_port)
	,	m_if				(findInterface(m_family))
	{
		Poco::Logger& logger = Poco::Util::Application::instance().logger();
		logger.information(Poco::format("  ReceiverTask start listening %s:%hu", args[0], m_port));

		m_multicastSocket.bind(Poco::Net::SocketAddress(Poco::Net::IPAddress(m_family), m_socketAddres.port()), true);
		m_multicastSocket.joinGroup(m_socketAddres.host(), m_if);
	}

	~ReceiverTask()
	{
	}
	
	void runTask()
	{
		Poco::Logger& logger = Poco::Util::Application::instance().logger();
		Poco::Timespan span(KWaitUSec);
		while(!isCancelled())
		{
			if(m_multicastSocket.poll(span, Poco::Net::Socket::SELECT_READ))
			{
				try
				{
					char buffer[256];
					Poco::Net::SocketAddress sender;
					int n = m_multicastSocket.receiveFrom(buffer, sizeof(buffer), sender);
					if(0 != n)
					{
						buffer[n] = 0;
						logger.information(Poco::format("   ReceiverTask: received %d bytes (%s)", n, std::string(buffer)));
					}
				//	m_multicastSocket.sendTo(buffer, n, sender);	// for echo back
				}
				catch(Poco::Exception& exc)
				{
					logger.information(Poco::format("   ReceiverTask: %s", exc.displayText()));
				}
			}
		}
	}

private:
	static Poco::Net::NetworkInterface findInterface(Poco::Net::IPAddress::Family family)
	{
		Poco::Net::NetworkInterface::NetworkInterfaceList ifs = Poco::Net::NetworkInterface::list();
		for(Poco::Net::NetworkInterface::NetworkInterfaceList::const_iterator itr=ifs.begin(); itr!=ifs.end(); ++itr)
		{
			if((family == itr->address().family()) && itr->address().isUnicast() && !itr->address().isLoopback())
			{
				if(	(Poco::Net::IPAddress::IPv4 == itr->address().family()) ||
					(Poco::Net::IPAddress::IPv6 == itr->address().family() &&
						std::string::npos != itr->address().toString().find("FE80::2"))	)
				// NOTE: "FE80::2" disables strange loppback address on Mac (fe80::1 <- usually ::1)
				{
					return *itr;
				}
			}
		}
		return Poco::Net::NetworkInterface();
	}

	Poco::Net::IPAddress::Family	m_family;
	Poco::UInt16					m_port;
	Poco::Net::MulticastSocket		m_multicastSocket;
	Poco::Net::SocketAddress		m_socketAddres;
	Poco::Net::NetworkInterface		m_if;
};

//----------------------------------------
//	MulticastSocketReceiver
//----------------------------------------
class MulticastSocketReceiver: public Poco::Util::ServerApplication
{
public:
	MulticastSocketReceiver()
	{
	}

protected:
	void initialize(Application& self)
	{
		loadConfiguration(); // load default configuration files, if present
		Poco::Util::ServerApplication::initialize(self);
		logger().information("   - MulticastSocketReceiver starting up");
	}
		
	void uninitialize()
	{
		logger().information("   - MulticastSocketReceiver shutting down");
		Poco::Util::ServerApplication::uninitialize();
	}

	int main(const std::vector<std::string>& args)
	{
		Poco::TaskManager tm;
		tm.start(new ReceiverTask(args));
		waitForTerminationRequest();
		tm.cancelAll();
		tm.joinAll();

		return Application::EXIT_OK;
	}
};

//----------------------------------------
//	entry point
//----------------------------------------
POCO_SERVER_MAIN(MulticastSocketReceiver)