How to marshal an object to a remote server by value by using Visual Basic 2005 or Visual Basic .NET (301116)



The information in this article applies to:

  • Microsoft Visual Basic 2005
  • Microsoft Visual Basic .NET (2003)
  • Microsoft Visual Basic .NET (2002)

This article was previously published under Q301116
For a Microsoft Visual C# 2005 and Visual C# .NET version of this article, see 307546.
For a Microsoft Visual Basic 6.0 version of this article, see 266717.

SUMMARY

This article demonstrates how to marshal an object by value to a remote server.

When you marshal an object by value, a copy of the object is created and serialized to the server. Any method calls made on that object are done on the server. Because the object must be serialized to the server, the class definition for the object you are passing must be annotated with the <Serializable> attribute. This article expands on the following Microsoft Knowledge Base articles:

300951 How to create a remote server by using Visual Basic .NET

300943 How to create client access to remote server by using Visual Basic .NET

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Windows Server 2003, Microsoft Windows XP, Microsoft Windows 2000 Professional, Microsoft Windows 2000 Server, Microsoft Windows 2000 Advanced Server, or Microsoft Windows NT 4.0 Server
  • Microsoft Visual Studio 2005 or Microsoft Visual Studio .NET
This article assumes that you are familiar with the following topics:
  • Microsoft Visual Basic 2005 or Microsoft Visual Basic .NET
  • Basic networking

Create the remote server object

The first step to creating the server application is to create your server object. The server object is what the client application instantiates and communicates with on the server computer. The client application does this through a proxy object that is created on the client. Your server object will reside in a class library (DLL) and is called HelloServer. In the same project you will also define the class that is going to be passed from the client to the server. This class will be called ForwardMe. Because you want the ForwardMe class to be passed by value, you will annotate it with the <Serializable> attribute.
  1. Start Visual Studio 2005 or Visual Studio .NET.
  2. Create a new Visual Basic 2005 or Visual Basic .NET class library application and name it ServerClassValue.
  3. In Solution Explorer, rename the file created by default from Class1.vb to ServerClassValue.vb.
  4. Open ServerClassValue.vb and add two classes called HelloServer and ForwardMe. HelloServer will inherit from MarshalByRefObject, while the ForwardMe class will use the <serializable> custom attribute. This tag will enable the ForwardMe class to be streamed to and from the server, which is what happens when passing an object by value to a remote server. The HelloServer class will be the main class used by the client application. The ForwardMe class will be used to send object data from the client to the server. Because ForwardMe does not inherit from MarshalByRefObject, it will be passed by value to the server. Your ServerClassValue.vb module should look like the following.
    Public Class HelloServer
    	Inherits MarshalByRefObject
    
    End Class
    <Serializable()> Public Class ForwardMe
    
    End Class
    					
  5. Add a public method to HelloServer called HelloMethod that takes a ForwardMe object. We will use this method to pass a ForwardMe object to the server. This method will call the CallMe method of that object. Your HelloServer class should now look like the following.
    Public Class HelloServer
        Inherits MarshalByRefObject
    
        Public Sub HelloMethod(ByRef obj As ForwardMe)
            Dim i As Integer
            obj.CallMe()
        End Sub
    End Class
    					
  6. Add a public method to the ForwardMe class. This method will get the name of the process where this code is being executed. Because you are serializing the whole object to the server (marshaling by value), the code will execute in the server's process.
    <Serializable()> Public Class ForwardMe
    
        Public Function CallMe() As Object
            Console.WriteLine("CallMe was executed in: " & _
            Process.GetCurrentProcess.ProcessName.ToString)
        End Function
    
    End Class
    					
  7. Build the project to create the ServerClassValue.dll assembly.
  8. Close and save the project.

Create the remote server application

Now that you have created the server object that your client will communicate with, you need to register this object with the Microsoft .NET Remoting Framework. Registering not only involves registering the object but also starting the server and having it listen on a port for clients to connect. To do this, you need a project type that will output an executable file. The reason you included the server object in a separate project was so that you could easily reference the server object from the client. If you included it in this project you could not reference it, because references can only be set to DLL files.
  1. Open Visual Studio 2005 or Visual Studio .NET.
  2. For simplicity's sake, create a new Visual Basic 2005 or Visual Basic .NET console application to start the remote server and name it ServerObjectValue.
  3. In Solution Explorer, rename the file created by default from Module1.vb to ServerObjectValue.vb.
  4. Add a reference to the System.Runtime.Remoting namespace to the project.
  5. Add a reference to the ServerClassValue.dll assembly created in the previous section.
  6. Use the Imports statement on the Remoting, Remoting.Channels, and Remoting.Channels.TCP namespaces so you will not be required to qualify declarations in those namespaces later in your code. The Imports statement must be used prior to any other declarations.
    Imports System.Runtime.Remoting
    Imports System.Runtime.Remoting.Channels
    Imports System.Runtime.Remoting.Channels.TCP
    					
  7. Declare the appropriate variable which will initialize a TcpChannel object that will listen for clients to connect on a certain port, in this case port 8085. Register the channel the client will use to communicate with the channel services by using the RegisterChannel method. Add the declaration code in the Main procedure in Module1.
    Dim chan As TcpChannel = New TcpChannel(8085)
    ChannelServices.RegisterChannel(chan)
    					
  8. Now register the ServerClassValue object with the .NET Remoting Framework by calling the RegisterWellKnownType method of the RemotingConfiguration object. You must specify the following pieces:
    1. The full type name of the object being registered, in this case ServerClassValue.HelloServer, followed by the assembly name, ServerClassValue. You must specify both the name of the namespace as well as the class name here. Since you did not specify a namespace in the previous section, the default root namespace is used.
    2. The name of the endpoint where the object will be published. Clients need to know this name in order to connect to the object. Use RemoteTestValue.
    3. The final parameter specifies the object mode, which can be SingleCall or Singleton. This example specifies SingleCall. The object mode specifies the lifetime of the object when it is activated on the server. In the case of SingleCall objects, a new instance of the class will be created for each call made from a client, even if the same client calls the same method more than once. Singleton objects, on the other hand, are created once only and all clients communicate with the same object.
      RemotingConfiguration.RegisterWellKnownServiceType( _
       Type.GetType("ServerClassValue.HelloServer, ServerClassValue"), _
       "RemoteTestValue", _
       WellKnownObjectMode.SingleCall)
      						
  9. Keep the server application running by using the ReadLine method of the Console object.
    Console.WriteLine("Hit <enter> to exit...")
    Console.ReadLine()
    					
  10. Build the project.
  11. Save and close the project.

Create the client application

  1. Start Visual Studio 2005 or Visual Studio .NET.
  2. Create a new console application in Visual Basic 2005 or in Visual Basic .NET and name it ClientAppValue.
  3. In Solution Explorer, rename the file created by default from Module1.vb to ClientAppValue.vb.
  4. Add a reference to the System.Runtime.Remoting namespace to the project.
  5. Add a reference to the ServerClassValue.dll assembly that you created earlier in this article.
  6. Use the Imports statements on the Remoting, Remoting.Channels, and Remoting.Channels.TCP namespaces so you will not be required to qualify declarations in those namespaces later in your code. The Imports statement must be used prior to any other declarations.
    Imports System.Runtime.Remoting
    Imports System.Runtime.Remoting.Channels
    Imports System.Runtime.Remoting.Channels.TCP
    					
  7. Declare the appropriate variable which will initialize a TcpChannel object that the client will use to connect to the server application. Register the channel with the channel services by using the RegisterChannel method.

    Secondly, you must initialize a new ForwardMe object that will be passed to the remote server object. Remember that this object is going to be passed by value. Add the declaration code in the Main procedure in Module1:
    Dim chan As TcpChannel = New TcpChannel()
    ChannelServices.RegisterChannel(chan)
    Dim objForwardMe As New ServerClassValue.ForwardMe()
    					
  8. Declare and instantiate the remote server. You will instantiate the HelloServer object by using the GetObject method of the Activator object. You must specify the following pieces:
    1. The full type name of the object being registered, in this case ServerClassValue.HelloServer, followed by the assembly name, ServerClassValue. You must specify both the name of the namespace as well as the class name here. Because you did not specify a namespace in the previous section, the default root namespace is used.
    2. The Uniform Resource Identifier (URI) of the object you want to activate. The URI must include the protocol (tcp), the computer name (localhost), the port (8085), and the endpoint of the server object (RemoteTestValue). To access the ServerClassValue remote server that is located on the local server, the URI is "tcp://localhost:8085/RemoteTestValue".
      Dim objHelloServer As ServerClassValue.HelloServer
      
      objHelloServer = CType(Activator.GetObject( _
      	Type.GetType("ServerClassValue.HelloServer, ServerClassValue"), _
      	"tcp://localhost:8085/RemoteTestValue"), _
      	ServerClassValue.HelloServer)
      If objHelloServer Is Nothing Then
      	Console.WriteLine("Could not locate server")
      Else
      	'See next step
      End If
      						
  9. If the server object is instantiated successfully, you should call the server object's HelloMethod, passing in the newly created objForwardMe object. Remember that the HelloMethod calls the CallMe method of the ForwardMe object, which displays the process name where the code is executing to the console window.
    Dim objHelloServer As ServerClassValue.HelloServer
    
    objHelloServer = CType(Activator.GetObject( _
        Type.GetType("ServerClassValue.HelloServer, ServerClassValue"), _
        "tcp://localhost:8085/RemoteTestValue"), _
        ServerClassValue.HelloServer)
    If objHelloServer Is Nothing Then
        Console.WriteLine("Could not locate server")
    Else
       objHelloServer.HelloMethod(objForwardMe)
       Console.WriteLine("Method executed, check server window for output.")
    End If
    					
  10. Keep the client application running by using the ReadLine method of the Console object:
    Console.WriteLine("Hit <enter> to exit...")
    Console.ReadLine()
    					
  11. Build the project.
  12. Make sure that the server application is running.
  13. Run the client project to test the client-to-server communication. When you run the client, you will receive notification when the method has finished executing. Notice that the output from the CallMe method was displayed in the server's console window, not in the client. This is because you marshaled the object to the server by value.

Modification Type:MinorLast Reviewed:10/3/2006
Keywords:kbvs2005swept kbvs2005applies kbHOWTOmaster KB301116 kbAudDeveloper