ServerEvents and ClientEvent in Remoting using VB.NET

In this article I will explain you about ServerEvents and ClientEvent in Remoting using VB.NET.
  • 2901

As you learn about Event and Delegates in Remoting using VB.NET in my previous article, now you will see the remaining part:The server creates an HttpChannel to send and receive messages. It registers both server-activated and client-activated SimpleObjects and waits for a client to call a method on the remote object. (See Listing 25.15.)

Listing 25.15: EventServer.vb

Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports SimpleEventLib 
Namespace EventServer
    Class ServerEvent
        Private Shared Sub Main(ByVal args As String())
            Dim http As HttpChannel = Nothing
            http = New HttpChannel(1234)
            RemotingConfiguration.RegisterWellKnownServiceType(GetType(SimpleObject), "Simple",
            RemotingConfiguration.ApplicationName = "Simple"
            Console.WriteLine("Press <enter> to exit.")
        End Sub
    End Class
End Namespace

Notice that the server-activated registration uses Singleton mode. There is no registration of the SyncRemoteEvent object. Running the server executable produces the output in Figure 25.10, while Figure 25.11 displays the client's output. 



Listing 25.16: EventClient.vb
Class ClientEvent
    Public Sub New()
        Console.WriteLine("In ClientEvent constructor")
    End Sub
    Private Shared Function Main(ByVal args As String()) As Integer
        Dim client As SyncRemoteEvent = Nothing
        Dim http As HttpChannel = Nothing
        http = New HttpChannel(2345)
        'client = (SyncRemoteEvent)ClientEvent.InitClientEvent();
        client = New SyncRemoteEvent()
        Dim simple As SimpleObject = Nothing
        simple = DirectCast(Activator.GetObject(GetType(SimpleObject), "http://localhost:1234/Simple"),
        simple.RemoteEvent += New RemoteEventHandler(client.EventHandler)
        Dim ret As String = Nothing
        ret = simple.ConCatString("using", "Activator.GetObject")
        simple.RemoteEvent -= New RemoteEventHandler(client.EventHandler)
        ret = simple.ConCatString("2 using", "Activator.GetObject")
        Return (0)
    End Function
End Class

The client creates a channel, but in this instance it specifies a port number (see Listing 25.16). The server must have a defined port number to contact the client during the event firing. The event handler is created with a simple new; no registration is required. The line commented out above the new operator will be discussed later. SimpleObject is a server-activated object because of the Activator.GetObject(). The code for a client-activated remote object could be Activator.CreateInstance() or as follows:

        RemotingConfiguration.RegisterActivatedClientType(GetType(SimpleObject), "http://localhost:1234/Simple")
        simple = New SimpleObject()

The client then subscribes to the event and calls SimpleObject.ConcatString() it then unsubscribes and makes a subsequent call to ConcatString().

While experimenting with remote events, we made an interesting discovery. As the code stands now, the event is fired from within the server's application domain to the client's. The client doesn't actually intercept the event unless the server has some reference to it. If, for example, ClientEvent was derived from SyncRemoteEvent, an exception would be thrown when it is registered with SimpleObject's event delegate-that is, unless the remoting framework is tricked into thinking it is dealing with a SyncRemoteEvent rather than a ClientEvent object. Deceiving the framework results in output such as that shown in Figure 25.12.

Figure 25.12: Event Client Output


Listing 25.17: EventClient.cs
Class ClientEvent
    Inherits SyncRemoteEvent
    Public Sub New()
        Console.WriteLine("In ClientEvent constructor")
    End Sub
    Private Shared Function InitClientEvent() As Object
        Dim client As SyncRemoteEvent = Nothing
        RemotingConfiguration.RegisterWellKnownServiceType(GetType(ClientEvent), "Event",
        client = DirectCast(Activator.GetObject(GetType(SyncRemoteEvent), "http://localhost:2345/Event"),
        Return DirectCast(client, Object)
    End Function

    Public Overrides Sub EventHandler(ByVal sender As Object, ByVal args As RemoteArgs)
        Console.WriteLine("In ClientEvent.EventHandler")
        Console.WriteLine("Machine:{0} Dir:{1}", args.MachineName, args.CurrentDir)
        MyBase.EventHandler(sender, args)
    End Sub
End Class

The first step in accomplishing direct event interception is to make the EventHandler() in SyncRemoteEvent a virtual method. Then, override the method in ClientEvent. Duping the framework takes place in the static method InitClientEvent(). Register the server-activated object as a type of ClientEvent in either SingleCall or Singleton mode. Then, Activator.GetObject() returns a transparent proxy of the requested type, SyncRemoteEvent. If you look at the output, a ClientEvent instance is created, but the proxy has been downcast to a SyncRemoteEvent instance. The result is that the server doesn't have any reference to ClientEvent. No exception is thrown during registration with the event delegate. Because the EventHandler() is virtual, the proper method is called. Experimenting with this as a client-activated object resulted in failure, no matter what twists and contortions were taken.


Hope this article would have helped you in understanding ServerEvents and ClientEvent in Remoting using VB.NET.


More Articles

© 2020 DotNetHeaven. All rights reserved.