//# //# Corba Time Server //# $Revision: 1.1 $ //# Copyright 2004 by Eric Y. Theriault //# All Rights Reserved. //# http://www.eyt.ca/CORBA //# using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Services; using System.Runtime.Remoting.Channels; using Ch.Elca.Iiop; using Ch.Elca.Iiop.Services; using omg.org.CosNaming; namespace ca.eyt.corba { /// /// Multicast Service. /// /// /// For more information on Multicasting, please see Chapter 21 [549] /// of W. Richard Stevens, Bill Fenner, and Andrew M. Rudoff's UNIX /// Network Programming: Volume 1: The Sockets Networking API--Third /// Edition, Addison-Wesley, 2004. /// class MulticastIORServer { /// /// Port to multicast on. This number is random. /// public const int MulticastPort = 7007; /// /// Address to multicast to. The default is link-local, which is /// generally OK, but in the presence of a segmented network with /// routers, this address and the TTL will have to be changed. /// public const String MulticastAddress = "224.0.0.1"; /// /// This is the message that is multicasted to discover the new /// server. /// public const String MulticastDiscoverServer = "DiscoverIOR"; /// /// IOR to Multicast /// private string ior; /// /// Multicast Socket /// private MulticastSocket mcast; /// /// Thread Reference. /// System.Threading.Thread thread; /// /// Create the service to answer to inbound Multicasts /// /// IOR of NameService public MulticastIORServer( String ior ) { this.ior = ior; // Please note that a real implementation would provide options // to set the bind address, Time To Live, etc., but this is // simply to demonstrate the functionality. mcast = new MulticastSocket( MulticastPort ); mcast.bind(); mcast.joinGroup( MulticastAddress ); } /// /// Executes the thread. /// protected void run() { while ( true ) { try { // Create a received String System.Net.IPEndPoint address = null; string receivedString = mcast.receive( ref address ); // If the packet is good, reply // // In a real application, a checksum or something could // be used to validate the message, and the reply should // contain a more verbose message. if ( receivedString.StartsWith( MulticastDiscoverServer ) ) { // Unicast back to the sender the ior string. mcast.send( address, ior ); } } catch ( Exception e ) { // Log the message. System.Console.WriteLine( "Exception: " + e.Message ); System.Console.WriteLine( e.StackTrace.ToString() ); } } } /// /// Starts a thread. /// public void start() { thread = new System.Threading.Thread( new System.Threading.ThreadStart( run ) ); thread.Start(); } } /// /// Implements a CORBA server to provide the local time. /// public class TimeServer { /// /// Server Port /// const int ServerPort = 7832; /// /// Main. /// [System.STAThread] public static void Main( string[] args ) { try { String iorFile = "time.ior"; // Create and Initialize the ORB CorbaInit orb = CorbaInit.GetInit(); // Register server channel IiopChannel channel = new IiopChannel( ServerPort ); ChannelServices.RegisterChannel( channel ); // Create the time Servant and register it. ca.eyt.corba.TimeImpl timeImpl = new ca.eyt.corba.TimeImpl(); // Create the object reference. string objectURI = "Time"; ObjRef objrefWellKnown = RemotingServices.Marshal( timeImpl, objectURI ); // Acquire the IOR for the object reference. //TODO: There is probably a nicer way to do this. omg.org.CORBA.OrbServices srv = omg.org.CORBA.OrbServices.GetSingleton(); String[] url = channel.GetUrlsForUri( objrefWellKnown.URI ); if ( url.Length != 1 ) { throw new Exception( "Unexpected input: " + url.Length ); } object obj = srv.string_to_object( url[0] ); String ior = srv.object_to_string( obj ); // Write out the file try { using ( System.IO.StreamWriter writer = new System.IO.StreamWriter( iorFile ) ) { writer.WriteLine( ior ); } } catch ( Exception e ) { System.Console.Error.WriteLine( iorFile + " raised an exception: " + e.Message ); System.Environment.Exit( 1 ); } // Let's get the root naming context. NamingContext nameService = ORBHelper.resolveNameserviceReference( orb, args ); // Bind the Time object to the reference. String Time = "Time"; NameComponent[] path = new NameComponent[] { new NameComponent( Time, "" ) }; nameService.rebind( path, timeImpl ); // Start the Multicast Server MulticastIORServer mcast = new MulticastIORServer( srv.object_to_string( nameService ) ); mcast.start(); // Server is now up and running System.Console.Out.WriteLine( "TimeServer is ready and waiting..." ); } catch ( System.Exception e ) { System.Console.WriteLine( "Exception: " + e.Message ); System.Console.WriteLine( e.StackTrace.ToString() ); System.Environment.Exit( 1 ); } } } }