I'd really appreciate help on the following.  I am working with remoting,
and am having a problem supporting both an http channel with a binary
formatter and an http channel with a soap formatter in the same client
application instance.  I setup a simple test below.  I have a remoting
server instance listening on one port for http binary, and a second port
for http SOAP, both serving the same type (InventoryService).

If I run the client with only the http channel with soap formatter, or the
http channel with only the binary formatter, the calls complete correctly
(per the conditional #defines at top).  If I run a test executing two
client applications concurrently, one with an http channel/soap formatter
and the second with the http channel/binary formatter, everything works
fine (i.e., the server handles it).  However if I run both http/soap and
http/binary channels within the same instance, I get an exception thrown.
It looks like the formatter isn't deserializing properly:

Unhandled Exception: System.Runtime.Remoting.RemotingException:
System.ArgumentNullException: No message was deserialized prior to calling
the DispatchChannelSink.
Parameter name: requestMsg
   at System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage
(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders
requestHeaders, Stream requestStream, IMessage& responseMsg,
ITransportHeaders& responseHeaders, Stream& responseStream)

1) Is it legitimate to run both http binary and soap channels within the
same client instance?  As far as I can tell, this should not pose a problem.

2) If it is legitimate, then shouldn't the remoting runtime properly select
the channel based upon the server the correct http channel to use based
upon the protocol supported by the server?  I don't see a way to force the
correct channel to be selected.

I can provide full source to anyone interested.  Client Code as follows:

#define TEST_HTTP_BINARY
#undef TEST_HTTP

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Collections;

namespace RemotingSample
{
    class TestClient
    {
        static ManualResetEvent ev = new ManualResetEvent(false);

        [STAThread]
        static void Main(string[] args)
        {
            Hashtable settings = new Hashtable();
            settings.Add("name", "tcp");
            settings.Add("port", "0");

            TcpChannel tcp = new TcpChannel(settings, null, null);
            ChannelServices.RegisterChannel(tcp);

            TestClient trc = new TestClient();

#if (TEST_HTTP)
            settings.Clear();
            settings.Add("name", "http");
            settings.Add("port", "0");
            HttpChannel http = new HttpChannel(settings, new
SoapClientFormatterSinkProvider(), new SoapServerFormatterSinkProvider());
            ChannelServices.RegisterChannel(http);
#endif

#if (TEST_HTTP_BINARY)
            settings.Clear();
            settings.Add("name", "httpbin");
            settings.Add("port", "0");
            HttpChannel httpbin = new HttpChannel(settings, new
BinaryClientFormatterSinkProvider(), new BinaryServerFormatterSinkProvider
());
            ChannelServices.RegisterChannel(httpbin);
#endif

            // gauge relative speed of different protocols and hosting
mechanisms
            // T1: tcp, binary
            Thread t1 = new Thread(new ThreadStart(trc.RunTest));
            t1.Name = "tcp://localhost:8089/Inventory";
            t1.Start();
            ev.WaitOne();
            ev.Reset();


#if (TEST_HTTP)
            // T2: http, soap
            Thread t2 = new Thread(new ThreadStart(trc.RunTest));
            t2.Name = "http://localhost:8090/Inventory";;
            t2.Start();
            ev.WaitOne();
            ev.Reset();
#endif
#if (TEST_HTTP_BINARY)
            // T3: http, binary
            Thread t3 = new Thread(new ThreadStart(trc.RunTest));
            t3.Name = "http://localhost:8091/Inventory";;
            t3.Start();
            ev.WaitOne();
            ev.Reset();
            // T4: http, binary, iis
            Thread t4 = new Thread(new ThreadStart(trc.RunTest));
            t4.Name = "http://localhost:80/InventoryService/Inventory.rem";;
            t4.Start();
            ev.WaitOne();
#endif
        }

        public void RunTest()
        {
            try
            {
                string url = Thread.CurrentThread.Name;
                Inventory.InventoryService invsvc =
(Inventory.InventoryService)Activator.GetObject(typeof
(Inventory.InventoryService), url);
                long start = DateTime.Now.Ticks;

                int i = 0;
                for(i = 0; i < 1000; i++)
                {
                    invsvc.CheckInventory("132456");
                }

                long elapsed = DateTime.Now.Ticks - start;
                elapsed /= 10000;       // Get into millsecs
                Console.WriteLine(elapsed + "ms elapsed for " + i + "
iterations(" + ((float) elapsed)/i + "ms per call, in call: " +
invsvc.ReportAverageTime() + ") on url: " + url);
            }
            finally
            {
                ev.Set();
            }
        }
    }
}

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to