Introduction
The request-response communication is a communication scenario where messages flow in both directions - request messages from the sender to the receiver and response messages from the receiver back to the sender.
The example below shows the server receiving messages and sending responses back to the client. It also shows how to implement the client sending messages to the server and receiving response messages.
The example is based on the Eneter Messaging Framework that provides components for various communication scenarios.
(The framework is free and 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.)
1. Define Message Types
For the request-response communication, you must define type of the request message and type of the response message.
And same as described in the previous part, you should consider what serialization will be used.
(Because the serialization can require some additional attributes in the declarations.)
In our example, we will use the binary serialization. The request message type is 'Person
' and the response type is the string.
using System;
namespace CommonTypes
{
[Serializable]
public class Person
{
public string Name { get; set; }
public int NumberOfItems { get; set; }
}
}
2. Implement the Server
The server below receives the message type of 'Person
' and sends back a simple response message type of string.
using System;
using CommonTypes;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.NamedPipeMessagingSystem;
namespace DuplexTypedMessageServer
{
class Program
{
static IDuplexTypedMessageReceiver<string, Person> myMessageReceiver;
static void Main(string[] args)
{
IMessagingSystemFactory aMessagingSystemFactory = new NamedPipeMessagingSystemFactory();
IDuplexInputChannel anDuplexInputChannel =
aMessagingSystemFactory.CreateDuplexInputChannel("//127.0.0.1/MyPipeName3");
ISerializer aSerializer = new BinarySerializer();
IDuplexTypedMessagesFactory aDuplexTypedMessagesFactory =
new DuplexTypedMessagesFactory(aSerializer);
myMessageReceiver = aDuplexTypedMessagesFactory.CreateDuplexTypedMessageReceiver<string, Person>();
myMessageReceiver.MessageReceived += OnMessageReceived;
myMessageReceiver.AttachDuplexInputChannel(anDuplexInputChannel);
Console.WriteLine("The service is listening. Press enter to stop.\n");
Console.ReadLine();
myMessageReceiver.DetachDuplexInputChannel();
}
static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<Person> e)
{
Console.WriteLine("Received Message:");
Console.WriteLine("Name: " + e.RequestMessage.Name);
Console.WriteLine("Number of items: " + e.RequestMessage.NumberOfItems.ToString());
Console.WriteLine();
string aResponseMessage = DateTime.Now.ToString();
myMessageReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
}
}
}
3. Implement the Client
The client below sends the message type of 'Person
' and receives the response message type of string.
using System;
using System.Windows.Forms;
using CommonTypes;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.NamedPipeMessagingSystem;
namespace DuplexTypedMessageClient
{
public partial class Form1 : Form
{
private IDuplexTypedMessageSender<string, Person> myMessageSender;
public Form1()
{
InitializeComponent();
OpenConnection();
}
private void OpenConnection()
{
IMessagingSystemFactory aMessagingSystemFactory = new NamedPipeMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessagingSystemFactory.CreateDuplexOutputChannel("//127.0.0.1/MyPipeName3");
ISerializer aSerializer = new BinarySerializer();
IDuplexTypedMessagesFactory aDuplexTypedMessagesFactory =
new DuplexTypedMessagesFactory(aSerializer);
myMessageSender = aDuplexTypedMessagesFactory.CreateDuplexTypedMessageSender<string, Person>();
myMessageSender.ResponseReceived += OnResponseReceived;
myMessageSender.AttachDuplexOutputChannel(anOutputChannel);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
myMessageSender.DetachDuplexOutputChannel();
}
private void button1_Click(object sender, EventArgs e)
{
Person aPerson = new Person();
aPerson.Name = NameTextBox.Text;
aPerson.NumberOfItems = int.Parse(NumberOfItemsTextBox.Text);
myMessageSender.SendRequestMessage(aPerson);
}
private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<string> e)
{
string aResponseMessage = e.ResponseMessage;
InvokeInUIThread(() => ReceivedResponseTextBox.Text = aResponseMessage);
}
private void InvokeInUIThread(Action action)
{
if (InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
}
}
And here are communicating applications:
CodeProject
My programming path started in 1987 when I got my first computer Sharp MZ-800.
It came with 8 bit CPU Z80, 64Kb RAM and the tape recorder. It was a great machine. I think I still have it somewhere.
I was fascinated and I started to write first programs. Eventually I became developer and software architect. I like innovations and clean nice solutions.