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.
- Start Visual Studio 2005 or Visual Studio .NET.
- Create a new Visual Basic 2005 or Visual Basic .NET class library application
and name it ServerClassValue.
- In Solution Explorer, rename the file created by default
from Class1.vb to ServerClassValue.vb.
- 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
- 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
- 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
- Build the project to create the ServerClassValue.dll
assembly.
- 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.
- Open Visual Studio 2005 or Visual Studio .NET.
- 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.
- In Solution Explorer, rename the file created by default
from Module1.vb to ServerObjectValue.vb.
- Add a reference to the System.Runtime.Remoting namespace to the project.
- Add a reference to the ServerClassValue.dll assembly created in the previous section.
- 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
- 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)
- 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:
- 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.
- 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.
- 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)
- Keep the server application running by using the ReadLine method of the Console object.
Console.WriteLine("Hit <enter> to exit...")
Console.ReadLine()
- Build the project.
- Save and close the project.
Create the client application- Start Visual Studio 2005 or Visual Studio .NET.
- Create a new console application in Visual Basic 2005 or in Visual Basic .NET and
name it ClientAppValue.
- In Solution Explorer, rename the file created by default
from Module1.vb to ClientAppValue.vb.
- Add a reference to the System.Runtime.Remoting namespace to the project.
- Add a reference to the ServerClassValue.dll assembly that you created earlier in this article.
- 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
- 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()
- 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:
- 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.
- 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
- 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
- Keep the client application running by using the ReadLine method of the Console object:
Console.WriteLine("Hit <enter> to exit...")
Console.ReadLine()
- Build the project.
- Make sure that the server application is running.
- 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.
REFERENCES For more information, visit the following Microsoft
Web sites:
Modification Type: | Minor | Last Reviewed: | 10/3/2006 |
---|
Keywords: | kbvs2005swept kbvs2005applies kbHOWTOmaster KB301116 kbAudDeveloper |
---|
|