Introduction
There are many solutions we can choose to exchange data between two (or more) different applications: Remoting, named pipes, TCP client-server etc. However, in all these technologies, the communicating applications must be connected when exchanging data, and your programs must always be prepared for a sudden connection break. It's too complicated for simple purposes.
After a few days of searching, I found the simplest way for data exchange. This solution uses the UdpClient
class to send and receive data.
Background
UdpClient
is defined in the System.Net.Sockets
namespace. It allows to send data to any host and any port and receive data from any other host. When an application sends data, it send to the HOST and PORT instead of sending it to the second application. Moreover, the second application might not even be working! There is no connection between these two applications, and this is the best feature of thise solution.
Let's see how this works.
First of all, you need to initialize a UdpClient
object in your program. There are many constructors of the UdpClient
class. All of these need to "know" what network protocol you choose and what port will be used to receive data from.
int port=65000
UdpClient u=new UdpClient(port, AddressFamily.InterNetwork);
As you can see in the listing above, I initialize the object u
with an arbitrary port number 65000, and the second parameter points to a suitable network protocol.
The application can now read all the data coming to port 65000 from other programs working on the same or even remote machines in the network.
To read (recieve data), you can use this chunk of code:
if (u.Available > 0)
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
string readData = ASCIIEncoding.UTF32.GetString(b);
}
First, I check how many bytes are ready to read at the port. This value you can get from the Available
property of UdpCleint
. So, if the quantity of "available" bytes is greater then zero, read these bytes with the Receive
method. The method Receive
requires a reference to the IPEndPoint
object that points to the IP of the host which sent the data. It also requires a port where data is sent from. As you can see, I use IpAdress.Any
to create IPEndPoint
. This means that I want to read data sent by any host. I also use 0 as the second parameter - it means I want to read data sent from any port. The Receive
method has a "blocking" behavoiur; this means that it waits until data will be available on the port. That's why I check the u.Available>0
condition before calling the Receive
method.
As for sending data, it is even easier than reading. Take a look at the following example:
int port=65001
string host="localhost";
UdpClient u1 = new UdpClient();
u1.Connect(host, p);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
u1.Close();
I create a new UdpClient
using the parameterless constructor. Next, I try to connect to another host and port. In my example, the host is "localhost"; this means that the application that I want to send data to works on the same machine. I repeat once again: when I use the method Connect, it doesn't mean that I connect with a second application, but only with a host and port.
Note that in the example, I use port 65001, so I don't send data to myself (i.e., to 65000) but to another application which can read at this port.
Now we can read and write. Let's suppose we have two applications: App1 and App2, both working on the same machine (localhost).
The first contains a UdpClient
object initialized as below:
UdpClient u=new UdpClient(65000, AddressFamily.InterNetwork);
and the second one:
UdpClient u=new UdpClient(65001, AddressFamily.InterNetwork);
Now App1 sends data to App2 using the following code:
string s = "This is app1 is anybody there?";
UdpClient u1 = new UdpClient();
u1.Connect("localhost", 65001);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
App2 receives data:
if (u.Available > 0)
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
string readData = ASCIIEncoding.UTF32.GetString(b);
}
and answers (sending a message to App1):
string s = "App2 here howdy";
UdpClient u1 = new UdpClient();
u1.Connect("localhost", 65000);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
Using the code
Below, I have placed a complete listing of the library which can be compiled to a DLL. It's a simple wrapper of the code listed above.
using System.Net;
using System.Net.Sockets;
namespace UDP
{
public class SimpleUDP
{
UdpClient u;
public SimpleUDP(int port)
{
u = new UdpClient(port, AddressFamily.InterNetwork);
}
public void Write(string s, string host, int p)
{
UdpClient u1 = new UdpClient();
u1.Connect(host, p);
u1.Send(ASCIIEncoding.UTF32.GetBytes(s), ASCIIEncoding.UTF32.GetByteCount(s));
u1.Close();
}
public string Read()
{
if (u.Available > 0)
{
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0);
byte[] b = u.Receive(ref e);
return ASCIIEncoding.UTF32.GetString(b);
}
return "";
}
public void Close()
{
u.Close();
u = null;
}
}
}
You may use the class SimpleUDP
in two or more applications. It's easy.
App1 uses the constructor and two methods to write to App2 and read from it.
SimpleUDP u=new SimpleUDP(65000)
string s = u.Read();
u.Write("How do you do App2");
and for App2, we use a similar code for read and write:
SimpleUDP u=new SimpleUDP(65001)
string s = u.Read();
u.Write("Welcome App1");