Search This Blog

Saturday, November 6, 2010

Silverlight: How to Receive Messages from Desktop Application

Summary: Simple example showing how Silverlight application can receive messages from a standalone desktop application.



Introduction
The article is a free continuation of How to Send Message to Desktop Application where the Silverlight application sends a text message to the desktop application.
Now I would like to show how the Silverlight application can receive text messages from the desktop application with using TCP connection.
(Actually, the example bellow shows the bidirectional communication between the Silverlight application and the desktop application.)

The implementation uses Eneter Messaging Framework.
(Full, not limited and for non-commercial usage free version of the framework can be downloaded from http://www.eneter.net/. The online help for developers can be found at http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html)

As mentioned in the previous article, the Silverlight communication via TCP has the following specifics:
  • The Silverlight framework requires the policy server.
  • The Silverlight framework allows only ports of range 4502 - 4532.

In addition:
  • The Silverlight application cannot be a TCP listener.

Therefore, if the Silverlight application wants to receive messages, it must open TCP connection to the listening desktop application and receive response messages.


Eneter Messaging Framework supports these specifics. It contains the policy server, wraps the low-level socket communication and allows the request-response communication via duplex channels.
The implementation is very simple.


Desktop Application
The desktop application is responsible for starting the policy server, for receiving messages and for sending messages back to the Silverlight application.

using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.StringMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;

namespace DesktopApplication
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // Start the policy server to be able to communicate with silverlight.
            myPolicyServer.StartPolicyServer();

            // Create duplex message receiver.
            // It can receive messages and also send back response messages.
            IDuplexStringMessagesFactory aStringMessagesFactory = new DuplexStringMessagesFactory();
            myMessageReceiver = aStringMessagesFactory.CreateDuplexStringMessageReceiver();
            myMessageReceiver.ResponseReceiverConnected += ClientConnected;
            myMessageReceiver.ResponseReceiverDisconnected += ClientDisconnected;
            myMessageReceiver.RequestReceived += MessageReceived;

            // Create TCP based messaging.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
            IDuplexInputChannel aDuplexInputChannel = aMessaging.CreateDuplexInputChannel("127.0.0.1:4502");

            // Attach the duplex input channel to the message receiver and start listening.
            // Note: Duplex input channel can receive messages but also send messages back.
            myMessageReceiver.AttachDuplexInputChannel(aDuplexInputChannel);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Close listenig.
            // Note: If the listening is not closed, then listening threads are not ended
            //       and the application would not be closed properly.
            myMessageReceiver.DetachDuplexInputChannel();

            myPolicyServer.StopPolicyServer();
        }

        // The method is called when a message from the client is received.
        private void MessageReceived(object sender, StringRequestReceivedEventArgs e)
        {
            // Display received message.
            InvokeInUIThread(() =>
                {
                    ReceivedMessageTextBox.Text = e.RequestMessage;
                });
        }


        // The method is called when a client is connected.
        // The Silverlight client is connected when the client attaches the output duplex channel.
        private void ClientConnected(object sender, ResponseReceiverEventArgs e)
        {
            // Add the connected client to the listbox.
            InvokeInUIThread(() =>
                {
                    ConnectedClientsListBox.Items.Add(e.ResponseReceiverId);
                });
        }

        // The method is called when a client is disconnected.
        // The Silverlight client is disconnected if the web page is closed.
        private void ClientDisconnected(object sender, ResponseReceiverEventArgs e)
        {
            // Remove the disconnected client from the listbox.
            InvokeInUIThread(() =>
                {
                    ConnectedClientsListBox.Items.Remove(e.ResponseReceiverId);
                });
        }

        private void SendButton_Click(object sender, EventArgs e)
        {
            // Send the message to all connected clients.
            foreach (string aClientId in ConnectedClientsListBox.Items)
            {
                myMessageReceiver.SendResponseMessage(aClientId, MessageTextBox.Text);
            }
        }

        // Helper method to invoke some functionality in UI thread.
        private void InvokeInUIThread(Action uiMethod)
        {
            // If we are not in the UI thread then we must synchronize 
            // via the invoke mechanism.
            if (InvokeRequired)
            {
                Invoke(uiMethod);
            }
            else
            {
                uiMethod();
            }
        }

        private TcpPolicyServer myPolicyServer = new TcpPolicyServer();
        private IDuplexStringMessageReceiver myMessageReceiver;
    }
}


Silverlight Application
The Silverlight application is responsible for sending text messages and for receiving response messages. (The communication with the policy server is invoked automatically by Silverlight before the connection is established.)

using System.Windows;
using System.Windows.Controls;
using Eneter.Messaging.EndPoints.StringMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;

namespace SilverlightApplication
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            // Create duplex message sender.
            // It can send messages and also receive messages.
            IDuplexStringMessagesFactory aStringMessagesFactory = new DuplexStringMessagesFactory();
            myMessageSender = aStringMessagesFactory.CreateDuplexStringMessageSender();
            myMessageSender.ResponseReceived += MessageReceived;

            // Create TCP based messaging.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
            IDuplexOutputChannel aDuplexOutputChannel = aMessaging.CreateDuplexOutputChannel("127.0.0.1:4502");

            // Attach the duplex output channel to the message sender
            // and be able to send messages and receive messages.
            myMessageSender.AttachDuplexOutputChannel(aDuplexOutputChannel);
        }

        // The method is called when a message from the desktop application is received.
        private void MessageReceived(object sender, StringResponseReceivedEventArgs e)
        {
            textBox2.Text = e.ResponseMessage;
        }

        // The method is called when the button to send message is clicked.
        private void SendMessage_Click(object sender, RoutedEventArgs e)
        {
            myMessageSender.SendMessage(textBox1.Text);
        }


        private IDuplexStringMessageSender myMessageSender;
    }
}


Communicating Applications
The picture bellow shows the communicating applications. The desktop applications sent the message 'Hello Silverlight' that was received by both Silverlight clients. The first Silverlight application sent the message 'Hi Desktop' that was received by the desktop application.


I hope you found the article useful. Any feedback is welcome.

6 comments:

  1. very interesting...
    well done.

    ReplyDelete
  2. Nice tutorial and awesome library.
    Thanx.

    ReplyDelete
  3. Thanks, I am really glad you like the framework.

    ReplyDelete
  4. This line
    IDuplexOutputChannel aDuplexOutputChannel = aMessaging.CreateDuplexOutputChannel("127.0.0.1:4502");
    should be
    IDuplexOutputChannel aDuplexOutputChannel = aMessaging.CreateDuplexOutputChannel("tcp://127.0.0.1:4502");

    ReplyDelete
  5. Very efficiently written information. It will be helpful to everyone who will use it, including me. Almost certainly I’m likely to bookmark your blog.

    ReplyDelete
  6. very promising library....This will really help me.Thank you

    ReplyDelete