1

I'm developing a simple application that will receive data from a hardware via TCP. I've searched a bit on the Internet how to develop a program to receive TCP data, but have not found anything that I'm happy with. It is either a very simplified descriptions of how to work with TCP in C # or it is description of advanced frameworks.

I want a simple best practice of how to organize the communication part of my program in a good object-oriented manner. Any suggestions?

Ideally, I want the different structures that are sent via TCP are stored in the corresponding struct in the program

structure of what is sent:

Head
{
  Int16    Mode;
  Time     Start_time //(Unix time)
  Int16    Number of records
}
for each record if mode == 1
  char[20]    Name_of_record
for each record
  float    Value_of_record //(hardware-specific float)
  Int16    Flag_of_record
Foot
{
  Time     Stop_time //(Unix time)
}

And this is sent once a minute. There is no overhead. It just sends out the value of all variables and no more

Edit I do not have any control over the server.

magol
  • 6,135
  • 17
  • 65
  • 120
  • IMHO, the most widely used approaches are [WCF netTCPBinding](http://msdn.microsoft.com/en-us/library/ms731343.aspx) and [sockets](http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx) – oleksii Aug 25 '12 at 11:03
  • There is an article in CodeProject called "A Complete TCP Server/Client Communication and RMI Framework in C#" implementation is [here](http://www.codeproject.com/Articles/155282/A-Complete-TCP-Server-Client-Communication-and-RMI) and usage is [here](http://www.codeproject.com/Articles/153938/A-Complete-TCP-Server-Client-Communication-and-RMI). Also there is a nice question in SO called "How to write a scalable Tcp/Ip based server" which is [here](http://stackoverflow.com/q/869744/704144). These links don't have the exact answer to your question but they may be useful in your situation. – Şafak Gür Aug 25 '12 at 11:09
  • But this requires that both the client and the server uses this framework? I have no control over the hardware I communicate with. The protocol is already defined. – magol Aug 25 '12 at 11:13
  • Can you give some details about the devices that send data? Do the lengths of the data they send is fixed? How do you get a message is completely received; do they send a delimiter? What is the protocol of the device? How many of them should be connected at the same time? You said "I do not have any control over the server." in your edit but I thought you're writing the server and you don't have control over the devices that connect to it; can you clarify? – Şafak Gür Aug 25 '12 at 11:21
  • I'm not so convinced that your immediate issue is TCP. You're saying that your data should be transmitted in good object-oriented manner; but your code shows a plain sequence of data fields. Sorry, but that is not OO. I suggest you first define a proper, polymorphic C# base type for your data (an `interface` or base `class`), derive specialised data types from it, and *then* think about which library/framework you could use to transmit all these. (Have you looked into WCF, btw.?) – stakx - no longer contributing Aug 25 '12 at 11:27
  • first thing, which hardware are you using to communicate with. there are several devices, which come with their apis, and those apis are used to communicate with them, else you need to write some code in order to fetch the data, from specific port. – Qasim Javaid Khan Aug 25 '12 at 11:03
  • The hardware is very odd. But communication is very straightforward. It just sends out the value of all variables without overhead – magol Aug 25 '12 at 11:06

2 Answers2

2

We can receive TCP messages using asynchronous communication.

Initialize Server Socket and try to connect:

// Specify the size according to your need.
private byte[] bytData = new byte[1024 * 50000];
private Socket oServerSocket;

private void WindowLoaded(object sender, RoutedEventArgs e)
{
    try
    {
        // We are using TCP sockets
        this.oServerSocket = new Socket(
        addressFamily: AddressFamily.InterNetwork,
        socketType: SocketType.Stream,
        protocolType: ProtocolType.Tcp);

        // Assign the any IP of the hardware and listen on port number which the hardware is sending(here it's 5656)
        var oIPEndPoint = new IPEndPoint(address: IPAddress.Any, port: 5656);

        // Bind and listen on the given address
        this.oServerSocket.Bind(localEP: oIPEndPoint);
        this.oServerSocket.Listen(backlog: 4);

        // Accept the incoming clients
        this.oServerSocket.BeginAccept(this.OnAccept, null);
        this.oLogger.WriteLog("Server started");
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
}

On Successful connection:

private void OnAccept(IAsyncResult ar)
{
    try
    {
        var oClientSocket = this.oServerSocket.EndAccept(asyncResult: ar);

        // Start listening for more clients
        this.oServerSocket.BeginAccept(callback: this.OnAccept, state: null);

        // Once the client connects then start receiving the commands from her
        oClientSocket.BeginReceive(
        buffer: this.bytData,
        offset: 0,
        size: this.bytData.Length,
        socketFlags: SocketFlags.None,
        callback: this.OnReceive,
        state: oClientSocket);
    }
    catch (Exception ex)
    {
        // Handle Exception
    }
}

Process the message received:

private void OnReceive(IAsyncResult ar)
{
    try
    {
        var oClientSocket = (Socket)ar.AsyncState;
        oClientSocket.EndReceive(asyncResult: ar);

        /* Process the data here

        BitConverter.ToInt32(value: this.bytData, startIndex: 0);
        string SomeString= Encoding.ASCII.GetString(bytes: this.bytData, index: 8, count: 5);

        */

        // Specify the size according to your need.
        this.bytData = null;
        this.bytData = new byte[1024 * 50000];
        oClientSocket.BeginReceive(
            buffer: this.bytData,
            offset: 0,
            size: this.bytData.Length,
            socketFlags: SocketFlags.None,
            callback: this.OnReceive,
            state: oClientSocket);
    }

    catch (Exception ex)
    {
        // Handle Exception
    }
}
Ramesh Durai
  • 2,666
  • 9
  • 32
  • 55
1

Usually the steps are the same:

1) Read the data from the tcp stream and store it in a buffer (usually byte arrays).

2) Continuously check the buffer (every time you update it) to determine whether a complete packet is arrived.

3) Parse the buffer and extract the packet to the desired OO object

4) Add the object to a queue to further processing or invoke a background thread to consume the packet object.

To send data through the output stream is pretty much the same in the inverse order.

Things can get complicated/noisy/a pain when dealing with the buffer. You'll need to deal with the binary data to determine when a packet ends and another begins. Of course this is relative to the protocol of the device you're communicating, if it send fixed length packets or start/stop byte(s) etc... At this point there is no standard solution since the code you'll write depends on the data sent by the device.

EDIT: You updated your question with a sample code, however is not the structure of the record that matter, that part is simple and verbose to write (if your struct has a int field you read 4 bytes from the buffer and write on that field using BitConverter class to convert bytes to int for example). You'll need to read the hardware manual to check the format it sends the data (again, start/stop bytes, fixed length etc..).

This is very abstract because it's specific to each case, there is no "baked solution". Also, seems like you do not understand how streams/tcp connections/binary packets works, what makes you think that this is a problem of tcp connections, but is not. Tcp connections is just byte streams sent over a network, you can use the same pattern to read binary data from files on your disk or from a serial port.

Marcelo De Zen
  • 9,439
  • 3
  • 37
  • 50