"... and no one shall work for money, and no one shall work for fame; But each for the joy of the working, and each, in his separate star, shall draw the thing as he sees it, for the god of things as they are"

-Kipling

 

RemCon:
Typed Object Transfer via TCP/IP

Summary

The purpose of this project is to demonstrate the process of sending a typed object via TCP/IP in C#. In addition, a useful "drop-in" library has been created which makes it simple to add such transfer functionality to any C# project. In other words, you can create a typed object with whatever data fields you wish and then send it across the connection where it appears at the other end as an instantiated object of the same type. The mechanics of the transfer are irrelevant to either the sending or receiving application and the data is exchanged transparently.

The project includes a demonstration Server and a Client which exchange data as a typed object. The Client software will function both in Windows and on a Linux box under Mono. The Server has only been tested on Windows 10 but will probably work under Mono

Using the TCPDataTransporter

Normally an application uses the C# socket library in order to set up a TCP transfer mechanism. This issue has been abstracted away in the RemCon project. To create a server you would simply use code like the following...

// set up our data transporter
TCPDataTransporter dataTransporter = new TCPDataTransporter(
       TCPDataTransporterModeEnum.TCPDATATRANSPORT_SERVER, 
       <tcpip address>, 
       <tcpip port>);
// set up the event so the data transporter can send us the data it recevies
dataTransporter.ServerClientDataEvent += ServerClientDataEventHandler;
... and the TCPDataTransporter library does the rest. For the client side (on either windows or Linux) you can set up the operations using code like...

// set up our data transporter
TCPDataTransporter dataTransporter = new TCPDataTransporter(
       TCPDataTransporterModeEnum.TCPDATATRANSPORT_CLIENT, 
       <tcpip address>, 
       <tcpip port>);
// set up the event so the data transporter can send us the data it recevies
dataTransporter.ServerClientDataEvent += ServerClientDataEventHandler;

Both the client and server code operate in a separate thread. After the TCPDataTransporter class is created, data can easily be sent by calling it's SendData() function. Data will be received in the application via the ServerClientDataEventHandler event handler. There are also in-band events sent via this event handler which tell both sides that the remote connection has connected or disconnected. This enables the application to take actions based on those state changes if it wishes to do so. The connection is full duplex - either side can initiate a send of data in an asynchronous manner.

Caveats

The data is sent between the client and server in a container class named ServerClientData. This is the only manner in which data is exchanged. Of course, you can rework the ServerClientData code to include whatever information you wish and since the data is transferred as a fully typed object, it can contain fields of any datatype. This can include user defined classes - as long as those classes are decorated with the [SerializableAttribute] attribute (this is necessary to make the transmission as an object possible).

Implicit in the concept of strongly typed object transfer is that both sides have knowledge of the class structure being transferred. This is necessary so that the receiving side of the transfer can de-serialize the incoming binary data and create an instantiated class from it. This means that both the server and client must share some common code. The ServerClientData class in the RemConCommon library serves this purpose.

The server created by the TCPDataTransporter class only accepts one inbound client connection. This was done to keep things simple. It would not be all that difficult to adapt it to accept multiple connections.

The connection made by the TCPDataTransporter class is not re-usable. In other words, you cannot get the same TCPDataTransporter class to re-connect. You can, however, just shut it down and create a new TCPDataTransporter object in order to create a new connection.

The TCPDataTransporter objects are completely independent. It is possible to have multiple copies running simultaneously in the same application as long as they are connecting to different remote TCP/IP endpoints.

The Sample Code

The RemCon Sample Applications are open source and released under the MIT License. You can download, clone or fork the RemCon Sample Projects at the following address:

https://github.com/OfItselfSo/RemCon

The operation of the sample projects is pretty straight-forward.

  1. Find out the IP address of your Windows machine and edit the RemConConstants.cs file in the RemConCommon project to use that address.
  2. Compile up the RemConWinServer project.
  3. Compile up the RemConWinClient project.
  4. Start the RemConWinServer server.
  5. Start the RemConWinClient client.

The server should always be running before the client tries to connect. Both applications are written to automatically connect at startup. Since this is a demonstration application, the information transferred is minimal. When the client connects the text box in the server will note this fact. Pressing the button on the server will send a ServerClientData object with simple hard coded information to the client. The client output the received data to the Console (and the log file) and will respond with an acknowledgement that the process was successful. The returning acknowledgement is also logged on the server.

Screenshots

The example screenshot below is the main form of the RemConWinServer sample application after it has exchanged several messages with a RemConWinClient.

License

The contents of this web page are provided "as is" without any warranty of any kind and without any claim to accuracy. Please be aware that the information provided may be out-of-date, incomplete, erroneous or simply unsuitable for your purposes. Any use you make of the information is entirely at your discretion and any consequences of that use are entirely your responsibility. All source code is provided under the terms of the MIT License.