IPPort/IPDaemon: Receiving fixed-length data records

When receiving data in a known format it may be desirable to accumulate incoming data until a preset number of bytes are received. For instance a data format may exists where 100 bytes represents a record of some kind.

The RecordLength property defines the number of bytes the component buffers before firing the DataIn event. The components that currently support RecordLength are IPDaemon and IPPort from the IPWorks toolkit, and SSHDaemon and SSHClient from IPWorks SSH. The following is a detailed explanation of how RecordLength can be used.

The default value of RecordLength is zero, meaning the component will fire DataIn as soon as data is available. Setting RecordLength will cause the component to buffer incoming data until the appropriate number of bytes is received. Resetting the value of RecordLength to zero at any time will flush the buffer and cause DataIn to fire.

RecordLength can be set within the Connected and DataIn events, or in the main thread of the program. This article will cover both approaches.

Setting RecordLength in the Connected and DataIn events

This approach can be useful when using server components like IPDaemon since RecordLength is maintained on a per-client level, and the ConnectionId is available through the Connected and DataIn event arguments. The initial value for RecordLength should be set in the Connected event, and logic for changing RecordLength can be implemented in the DataIn event.

Below is an example of setting RecordLength in the Connected event, and updating it in the DataIn event: //Connected event handler static void daemon_OnConnected(object sender, IpdaemonConnectedEventArgs e) { ipdaemon.Connections[e.ConnectionId].RecordLength = 4; } //DataIn event handler static void daemon_OnDataIn(object sender, IpdaemonDataInEventArgs e) { Console.WriteLine("Server received " + e.TextB.Length + " bytes: " + e.Text); if (ipdaemon.Connections[e.ConnectionId].RecordLength == 4) { //Reset the RecordLength to 0 for this client. DataIn will fire as bytes are received. ipdaemon.Connections[e.ConnectionId].RecordLength = 0; } } static void Main(string[] args) { ipdaemon = new Ipdaemon(); ipport = new Ipport(); ipdaemon.OnConnected += new Ipdaemon.OnConnectedHandler(daemon_OnConnected); ipdaemon.OnDataIn += new Ipdaemon.OnDataInHandler(daemon_OnDataIn); ipdaemon.Listening = true; ipport.Connect("localhost", ipdaemon.LocalPort); Thread.Sleep(100); string data = "Four bytes will be received, then all the rest"; ipport.DataToSend = data; while (true) ipdaemon.DoEvents(); }

Setting RecordLength in the main thread of the program

RecordLength can also be set and modified outside the Connected and DataIn events. Resetting RecordLength to 0 with data in the buffer will cause DataIn to be fired with all buffered bytes.

Below is an example of buffering, flushing the buffer, and buffering again: ipdaemon = new Ipdaemon(); ipport = new Ipport(); ipdaemon.OnConnected += (o, e) => { connectionID = e.ConnectionId; }; ipdaemon.OnDataIn += (o, e) => { Console.WriteLine("Server received " + e.TextB.Length + " bytes: " + e.Text); }; ipdaemon.Listening = true; ipport.Connect("localhost", ipdaemon.LocalPort); Thread.Sleep(100); string data = "Hello World!"; //12 bytes ipdaemon.Connections[connectionID].RecordLength = 8; ipport.DataToSend = data; //send 12 bytes, DataIn will fire with 8 Thread.Sleep(100); ipdaemon.Connections[connectionID].RecordLength = 0; //flush 4 remaining bytes Thread.Sleep(100); ipport.DataToSend = data; //send 12 bytes, DataIn will fire with all 12 Thread.Sleep(100); ipdaemon.Connections[connectionID].RecordLength = 24; ipport.DataToSend = data; //send 12 bytes, component will buffer Thread.Sleep(100); ipport.DataToSend = data; //send 12 more bytes, DataIn will fire with 24 while (true) ipdaemon.DoEvents();

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.