I once again used the trick of taking the code from the previous example for the client. The File Transport client uses the same binding class as the server. This isn't actually a hard requirement in WCF. We never force you to share code between the client and server if you don't want to. It's sufficient for the client and server bindings to merely be compatible. However, I didn't have a good reason to demonstrate this in the example so I reused the existing binding.

The timeouts I'm using for the client and server are somewhat arbitrary. File operations of this size shouldn't take five seconds unless you've got a very slow device or you're trying to access files on a network share. The server has a one minute timeout waiting for incoming connections. That should be plenty of time to go start a client for testing but still short enough that you can sit and watch the server terminate gracefully when the timeout expires.

The description of the message protocol is in yesterday's post about the server.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using FileTransport;

namespace FileRequestChannelClient
{
   class FileRequestChannelClient
   {
      static void Main(string[] args)
      {
         Console.Write("Creating factory...");
         Binding binding = new FileTransportBinding();
         IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>();
         factory.Open(TimeSpan.FromSeconds(5));
         Console.WriteLine(" done.");
         Console.Write("Creating channel...");
         using (factory)
         {
            Uri uri = new Uri("my.file://localhost/x");
            IRequestChannel channel = factory.CreateChannel(new EndpointAddress(uri));
            Console.WriteLine(" done.");
            Console.Write("Opening channel...");
            channel.Open(TimeSpan.FromSeconds(5));
            Console.WriteLine(" done.");
            while (true)
            {
               Console.Write("Enter some text (Ctrl-Z to quit): ");
               String text = Console.ReadLine();
               if (text == null)
               {
                  break;
               }
               Console.Write("Sending request...");
               Message requestMessage = Message.CreateMessage(MessageVersion.Default, "http://reflect", text);
               Message replyMessage = channel.Request(requestMessage, TimeSpan.FromSeconds(5));
               Console.WriteLine(" done.");
               using (replyMessage)
               {
                  Console.WriteLine("Processing reply: {0}", replyMessage.Headers.Action);
                  Console.WriteLine("Reply: {0}", replyMessage.GetBody<string>());
               }
            }
            channel.Close(TimeSpan.FromSeconds(5));
         }
      }
   }
}

Next time: Counting Down to TechEd 2006