Microsoft KB Archive/818062

= How to marshal an object to a remote server by reference by using Visual C++ .NET or Visual C++ 2005 =

Article ID: 818062

Article Last Modified on 5/16/2007

-

APPLIES TO


 * Microsoft Visual C++ 2005 Express Edition
 * Microsoft Visual C++ .NET 2003 Standard Edition
 * Microsoft Visual C++ .NET 2002 Standard Edition
 * Microsoft .NET Framework 1.1
 * Microsoft .NET Framework 1.0

-







For a Microsoft Visual C# .NET version of this article, see 307600.



For a Microsoft Visual Basic .NET version of this article, see 301112.



This article refers to the following Microsoft .NET Framework Class Library namespaces:
 * System.Diagnostics
 * System.Runtime.Remoting
 * System.Runtime.Remoting.Channels
 * System.Runtime.Remoting.Channels.Tcp

IN THIS TASK
 * SUMMARY
 * Requirements
 * Create a Remote Server Object by Passing Objects
 * Create a Remote Server Application
 * Create a Client to a Remote Server by Passing Objects
 * REFERENCES



SUMMARY
This step-by-step article describes how to marshal an object by reference to a remote server. When you marshal an object by reference, the runtime creates a transparent proxy so that the server can make callbacks to the object on the client. Only the proxy is sent to the server. The proxy marshals the callbacks to the client.

back to the top



Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you will need:
 * Microsoft Windows Server 2003, Microsoft Windows 2000 Professional, Windows 2000 Server, Windows 2000 or Advanced Server Windows NT 4.0 Server
 * Microsoft Visual Studio .NET or Microsoft Visual Studio 2005

This article assumes that you are familiar with the following topics:
 * Visual Studio .NET or Visual Studio 2005
 * Basic networking

back to the top

Create a Remote Server Object by Passing Objects
The first step to create the server application is to create your server object. Your server object is what the client application creates an instance of and what communicates with the server computer. The client application communicates through a proxy object that is created on the client. Your server object that is named HelloServer is located in a class library (DLL). In the same project, you also define the class that you pass from the client to the server. This class is named ForwardMe. Because you want the ForwardMe class to be marshaled by reference, the ForwardMe class must inherit from the MarshalByRefObject class.  Start Visual Studio .NET or Visual Studio 2005. On the File menu, point to New, and then click Project. In Visual Studio .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Class Library under Templates.

In Visual Studio .NET 2003, click Visual C++ Projects under Project Types, and then click Class Library (.NET) under Templates.

In Visual Studio 2005, click Visual C++ under Project Types, and then click Class Library under Templates. Name the project ServerClassRef .  Open the ServerClassRef.cpp code file. Import the System.Diagnostics namespace so that you do not have to fully qualify names later in your code. using namespace System; using namespace System::Diagnostics; </li>  Add the HelloServer class and the ForwardMe class. Both classes inherit from MarshalByRefObject. The HelloServer class is the main class that the client application uses. The ForwardMe class sends object data from the client to the server. __gc public class ForwardMe : public MarshalByRefObject { };
 * 1) using <System.Dll>

__gc public class HelloServer : public MarshalByRefObject { }; Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the whole code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps: <ol style="list-style-type: lower-alpha;"> Click Project, and then click  Properties.

Note  is a placeholder for the name of the project.</li> Expand Configuration Properties, and then click General.</li> Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.</li></ol>

For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)

http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

</li>  Add a public method that is named HelloMethod to HelloServer that takes a ForwardMe object. You use this method to pass a ForwardMe object to the server. This method calls the CallMe method of that object. Your HelloServer class appears as follows: __gc public class HelloServer : public MarshalByRefObject { public: void HelloMethod(ForwardMe* obj ) {          obj->CallMe; }

}; </li>  Add a public method to the ForwardMe class, and name this method according to the process that runs this code. Because you are sending a proxy stub to the server and making call backs to the client (marshal by reference), the code runs in the process of the client. __gc public class ForwardMe : public MarshalByRefObject { public: void CallMe {       Console::WriteLine(&quot;CallMe was executed in: {0}&quot;, Process::GetCurrentProcess->ProcessName); }

}; </li> Build the project to create the ServerClassRef.dll assembly.</li> Save and close the project.</li></ol>

back to the top

Create a Remote Server Application
After you create the server object that your client communicates with, you must register this object with the .NET Framework. Registering the object also involves starting the server and communicating with the client. To do this, you must have a project type that creates an executable. The server object is included in a separate project so that you can easily reference the server object from the client project. <ol> Start Visual Studio .NET or Visual Studio 2005.</li> On the File menu, point to New, and then click Project.</li> In Visual Studio .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Application under Templates.

In Visual Studio .NET 2003, click Visual C++ Projects under Project Types, and then click Console Application (.NET) under Templates.

In Visual Studio 2005, click Visual C++ under Project Types, and then click CLR Console Application under Templates.</li> Name the project ServerObjectRef, and then click OK.</li>  Open the ServerObjectRef.cpp code file. Use the following code to add a reference to the System.Runtime.Remoting namespace.  Add a reference to the ServerClassRef.dll assembly that you created in the Create a Remote Server Object by Passing Objects section. Note To specify assembly search path, follow these steps: <ol style="list-style-type: lower-alpha;"> Open the Property Pages dialog box for the project.</li> <li>Open the C/C++ folder.</li> <li>Click the General tab.</li> <li>Modify the Resolve #using References property to the folder where the ServerClassRef.dll assembly exists.</li></ol> </li> <li> Use the using statement on the Remoting, Remoting.Channels, and Remoting.Channels.Tcp namespaces so that you do not have to qualify declarations in those namespaces later in your code. Use the using statement before any other declarations: using namespace System; using namespace System::Runtime::Remoting; using namespace System::Runtime::Remoting::Channels; using namespace System::Runtime::Remoting::Channels::Tcp; </li> <li> Declare a variable to initialize a TcpChannel object that listens for clients to connect on a port (in this sample, the port is 8085). Use the RegisterChannel method to register the channel that the client uses to communicate with the channel services. Add the declaration code in the Main procedure in Class1: TcpChannel* chan = new TcpChannel(8085); ChannelServices::RegisterChannel(chan); </li> <li>Call the RegisterWellKnownType method of the RemotingConfiguration object to register the ServerClassRef object with the .NET Framework. Specify the following parameters in the code: <ol style="list-style-type: lower-alpha;"> <li>The name of the object that is registered.</li> <li>The name of the endpoint where the object is published. Clients must know this name to connect to the object. For example, use RemoteTestRef.</li> <li> The object mode. This 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. For SingleCall objects, a new instance of the class is created for each call that a client makes, even if the same client calls the same method more than one time. However, Singleton objects are created only one time, and all clients communicate with the same object. Type* objType = __typeof(HelloServer); RemotingConfiguration::RegisterWellKnownServiceType(objType,&quot;RemoteTestRef&quot;,WellKnownObjectMode::SingleCall); </li></ol> </li> <li> Use the ReadLine method of the Console object to keep the server application running: Console::WriteLine(&quot;Press <ENTER> to exit...&quot;); Console::ReadLine; </li> <li>Build your project.</li> <li>Save and close the project.</li></ol>
 * 1) using <System.Dll>
 * 2) using <System.Runtime.Remoting.Dll> </li>
 * 1) using &quot;ServerClassRef.dll&quot;

back to the top

Create a Client to a Remote Server by Passing Objects
<ol> <li>Start Visual Studio .NET or Visual Studio 2005.</li> <li>In Visual Studio .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Application under Templates.

In Visual Studio .NET 2003, click Visual C++ Projects under Project Types, and then click Console Application (.NET) under Templates.

In Visual Studio 2005, click Visual C++ under Project Types, and then click CLR Console Application under Templates.</li> <li>Name the project ClientAppRef, and then click OK.</li> <li> Open the ClientAppRef.cpp code file. Use following code to add a reference to the System and System.Runtime.Remoting namespaces: <li> Add a reference to the ServerClassRef.dll assembly that you created in the Create a Remote Server Object by Passing Objects section. Note To specify assembly search path, follow these steps: <ol style="list-style-type: lower-alpha;"> <li>Open the Property Pages dialog box for the project.</li> <li>Open the C/C++ folder.</li> <li>Click the General tab.</li> <li>Modify the Resolve #using References property to the folder where the ServerClassRef.dll assembly exists.</li></ol> </li> <li> Use the using statement on the Remoting namespace, the Remoting.Channels namespace, and the Remoting.Channels.Tcp namespace so that you do not have to qualify declarations in those namespaces later in your code. Use the using statement before any other declarations: using namespace System::Runtime::Remoting; using namespace System::Runtime::Remoting::Channels; using namespace System::Runtime::Remoting::Channels::Tcp; using namespace ServerClassRef; </li> <li> Declare a variable to initialize a TcpChannel object that the client uses to connect to the server application. Specify the port when you initialize the TcpChannel object to enable bidirectional communication. You must do this because you are marshaling an object by reference, and the server uses this port to make callbacks to the client. The port should differ from the one that is used to send data. Use the RegisterChannel method to register the channel with the channel services. Initialize a new ForwardMe object that is passed to the remote server. Add the declaration code in the Main function as follows: TcpChannel* chan = new TcpChannel(8086); ChannelServices::RegisterChannel(chan); ForwardMe* objForwardMe = new ForwardMe; </li> <li>Declare and instantiate the remote server. In this case, use the GetObject method of the Activator object to instantiate the HelloServer object. Specify the following parameters in the code: <ol style="list-style-type: lower-alpha;"> <li>The full type name of the object that is registered (in this example, it is ServerClassRef.HelloServer) followed by the ServerClassRef assembly name. Specify both the name of the namespace and the name of the class. Because you did not specify a namespace in the previous section, the default root namespace is used.</li> <li> The uniform resource identifier (URI) of the object that you must activate. The URI must include the protocol (tcp), the computer name (localhost), the port (8085), and the endpoint of the server object (RemoteTestRef). Use the following URI to access the ServerClass remote server:
 * 1) using <System.Dll>
 * 2) using <System.Runtime.Remoting.Dll> </li>
 * 1) using &quot;ServerClassRef.dll&quot;

tcp://localhost:8085/RemoteTestRef

HelloServer* objHelloServer;

objHelloServer = static_cast<HelloServer*> (Activator::GetObject( __typeof(HelloServer), &quot;tcp://localhost:8085/RemoteTestRef&quot;)); if (objHelloServer == NULL) Console::WriteLine(&quot;Could not locate server&quot;); else {   // see the next step } </li></ol> </li> <li> If the server object is instantiated successfully, you can call the method of the server object and pass in the newly created objForwardMe object. This returns the modified string that you want to display. HelloServer* objHelloServer;

objHelloServer = static_cast<HelloServer*> (Activator::GetObject( __typeof(HelloServer), &quot;tcp://localhost:8085/RemoteTestRef&quot;)); if (objHelloServer == NULL) Console::WriteLine(&quot;Could not locate server&quot;); else {   objHelloServer->HelloMethod(objForwardMe); } </li> <li> Use the ReadLine method of the Console object to keep the client application running: Console::WriteLine(&quot;Press <ENTER> to exit...&quot;); Console::ReadLine; </li> <li>Build your project.</li> <li>Make sure that the server application is running.</li> <li>Run the project, and then test the client-to-server communication.</li></ol>

The output appears in the Console window of the client. Because you are marshaling by reference, callbacks are made to the client.

Note ServerClassRef.dll is located in the \ServerObjectRef\Debug and the \ClientAppRef\Debug directories.

back to the top

<div class="references_section">