tags:

views:

140

answers:

2

I'm writing a simple console client-server app using MSMQ. I'm attempting to run it over the workgroup we have set up. They run just fine when run on the same computer, but I can't get them to connect over the network. I've tried adding Direct=, OS:, and a bunch of combinations of other prefaces, but I'm running out of ideas, and obviously don't know the right way to do it. My queue's don't have GUIDs, which is also slightly confusing. Whenever I attempt to connect to a remote machine, I get an invalid queue name message. What do I have to do to make this work?

Server:

class Program
{
    static string _queue = @"\Private$\qim";
    static MessageQueue _mq;
    static readonly object _mqLock = new object();

    static void Main(string[] args)
    {
        _queue = Dns.GetHostName() + _queue;
        lock (_mqLock)
        {
            if (!MessageQueue.Exists(_queue))
                _mq = MessageQueue.Create(_queue);
            else
                _mq = new MessageQueue(_queue);
        }
        Console.Write("Starting server at {0}:\n\n", _mq.Path);
        _mq.Formatter = new BinaryMessageFormatter();
        _mq.BeginReceive(new TimeSpan(0, 1, 0), new object(), OnReceive);
        while (Console.ReadKey().Key != ConsoleKey.Escape) { }
        _mq.Close();
    }

    static void OnReceive(IAsyncResult result)
    {
        Message msg;
        lock (_mqLock)
        {
            try
            {
                msg = _mq.EndReceive(result);
                Console.Write(msg.Body);
            }
            catch (Exception ex)
            {
                Console.Write("\n" + ex.Message + "\n");
            }
        }
        _mq.BeginReceive(new TimeSpan(0, 1, 0), new object(), OnReceive);
    }
}

Client:

class Program
{
    static MessageQueue _mq;

    static void Main(string[] args)
    {
        string queue;
        while (_mq == null)
        {
            Console.Write("Enter the queue name:\n");
            queue = Console.ReadLine();
            //queue += @"\Private$\qim";
            try
            {
                if (MessageQueue.Exists(queue))
                    _mq = new MessageQueue(queue);
            }
            catch (Exception ex)
            {
                Console.Write("\n" + ex.Message + "\n");
                _mq = null;
            }
        }
        Console.Write("Connected. Begin typing.\n\n");
        _mq.Formatter = new BinaryMessageFormatter();
        ConsoleKeyInfo key = new ConsoleKeyInfo();
        while (key.Key != ConsoleKey.Escape)
        {
            key = Console.ReadKey();
            _mq.Send(key.KeyChar.ToString());
        }
    }
}
+1  A: 

You need to use this format to connect to a remote private queue:

FormatName:Direct=OS:machinename\\private$\\queuename

There's a handy article here with a bit more info

Stuart Dunkeld
I just tried that, and says it's unable to determine if the queue exists or not.
Daniel Rasmussen
From the docs for Exists: "Exists(String) cannot be called to verify the existence of a remote private queue"See http://blogs.msdn.com/b/johnbreakwell/archive/2008/07/31/checking-if-msmq-queues-exist-is-hard-work-so-should-you-bother.aspx for an alternative.
Stuart Dunkeld
Ah. Perhaps I'll just rely on the `Try` statement then.
Daniel Rasmussen
+1  A: 

I got that working, once. My recommendation would be 1: don't do it, 2: don't do it, 3: only use private queues and assign the workstations static IP addresses in the 192.168.x.x subnet. Either provide each machine with a hostfile to map machine names to IP addresses or use the IP address directly in the format name. Relying on name resolution in a work group is hoping to win playing roulette in Vegas.

Hans Passant