TCPClient/TCPServer: 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 is received. For instance, a data format may exist where 100 bytes represent a record of some kind.
The ChangeRecordLength method defines the number of bytes the component buffers before firing the DataIn event. The components that support this method are TCPClient and TCPServer in IPWorks, and SSHClient and SSHServer in IPWorks SSH. For TCPServer and SSHServer, the record length is set separately for each connection or channel, and the current value is available through the RecordLength field of the corresponding item in the Connections or Channels collection.
By default, the record length is 0, meaning that the component fires DataIn as soon as data is available. Setting a positive record length causes the component to buffer incoming data until that number of bytes has been received. Changing the record length back to 0 at any time flushes the buffer, causing DataIn to fire with any data that has already been received.
The record length can be changed within the Connected and DataIn events, or from the main thread of the program. This article covers both approaches.
Note that in older versions of IPWorks, the TCPClient and TCPServer components were named IPPort and IPDaemon, respectively, and the record length was set using a writable RecordLength property.
Changing the Record Length in the Connected and DataIn Events
This approach is useful with server components like TCPServer, since the record length is maintained separately for each client, and the ConnectionId is available in the Connected and DataIn event arguments. The initial record length can be set in the Connected event, and logic for changing it can be implemented in the DataIn event.
TCPServer tcpserver = new TCPServer();
TCPClient tcpclient = new TCPClient();
// Receive the first 4 bytes from each client as a single record.
tcpserver.OnConnected += (s, e) => {
tcpserver.ChangeRecordLength(e.ConnectionId, 4);
};
tcpserver.OnDataIn += (s, e) => {
Console.WriteLine("Server received " + e.TextB.Length + " bytes: " + e.Text);
if (tcpserver.Connections[e.ConnectionId].RecordLength == 4) {
// Reset the record length to 0 for this client. DataIn will now fire as bytes are received.
tcpserver.ChangeRecordLength(e.ConnectionId, 0);
}
};
tcpserver.LocalPort = 7777;
tcpserver.StartListening();
tcpclient.ConnectTo("localhost", 7777);
tcpclient.SendText("Four bytes will be received, then all the rest");
while (true) tcpserver.DoEvents();
Changing the Record Length from the Main Thread
The record length can also be changed outside of the Connected and DataIn events. Changing the record length to 0 while data is in the buffer causes DataIn to fire with all of the buffered bytes.
The example below buffers data, flushes the buffer, and then buffers data again:
TCPServer tcpserver = new TCPServer();
TCPClient tcpclient = new TCPClient();
string connectionId = "";
tcpserver.OnConnected += (s, e) => { connectionId = e.ConnectionId; };
tcpserver.OnDataIn += (s, e) => {
Console.WriteLine("Server received " + e.TextB.Length + " bytes: " + e.Text);
};
tcpserver.LocalPort = 7777;
tcpserver.StartListening();
tcpclient.ConnectTo("localhost", 7777);
Thread.Sleep(100);
string data = "Hello World!"; // 12 bytes
tcpserver.ChangeRecordLength(connectionId, 8);
tcpclient.SendText(data); // Send 12 bytes. DataIn fires with 8 bytes.
Thread.Sleep(100);
tcpserver.ChangeRecordLength(connectionId, 0); // Flush the 4 remaining bytes.
Thread.Sleep(100);
tcpclient.SendText(data); // Send 12 bytes. DataIn fires with all 12 bytes.
Thread.Sleep(100);
tcpserver.ChangeRecordLength(connectionId, 24);
tcpclient.SendText(data); // Send 12 bytes. The component buffers them.
Thread.Sleep(100);
tcpclient.SendText(data); // Send 12 more bytes. DataIn fires with 24 bytes.
while (true) tcpserver.DoEvents();
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.