Click here to Skip to main content
15,893,401 members
Articles / All Topics

TCP Frame Delimiting & Receive Pattern

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
21 Apr 2015CPOL4 min read 8.8K   2   2
TCP Frame Delimiting & Receive Pattern

Recently, I was on premises at a client who uses custom network protocols quite heavily. The nature of their business, together with existing architecture, was such that almost all of the network communications in their enterprise happens using TCP sockets and their own custom rolled protocols. As much as I advocate using existing proven technologies and protocols, one does come across these scenarios every so often.

While I was there, I was asked about receiving data over TCP and how I like to delimit frames sent over the network. Normally, this is a trivial scenario that does not require any sort of pattern and is easily implemented without much thought. However, in this situation, the team of developers was sizeable, the focus of the architecture diverse and all-in-all, it begged for some form of standardization. That got me thinking about a simple strategy for the network data receipt in .NET.

There are a number of methods developers use to delimit frames sent over a TCP socket. Here are a few I can think about:

  • Fixed Length Frames – This method involves sending frames to the remote host as preconfigured fixed sized frames. While this method is very easy to code for, it is extremely inefficient when the data contained in the frames vary greatly in size. Sending data of 500 bytes in a fixed length frame of 1024 in size means that you are essentially wasting 524 bytes of frame capacity.
  • Pattern Delimited Frames – With this method, the receiving application scans the incoming network data for a specific sequence of bytes. When the particular sequence is found, it means that all data read up to that point is in a frame and all data after that point is a new frame. While this is much more bandwidth efficient than the first method, it can become quite complex to implement. What if the data sent coincidentally contains the delimiting pattern of bytes? The developer would then have to consider escaping those sequences amongst other complications.
  • Frame Length Specified as a Frame Header – This is by far the most popular method of indicating frame boundaries. A known fixed portion of the frame contains the length of either the data part or the entire frame. This is fairly easy to implement, but scenarios can arise that caused complications; the bytes that indicate the length of the frame, may vary in length themselves; the position of the length bytes my change from one frame type to another.

Keeping these methods in mind as well as potentially more complex methods, I came up with a simple library that seemed sufficient for the organization, and is general enough to be most scenarios. It uses a strategy pattern to separate frame boundary calculations from other logic. This gives the developer the convenience of “receiving” only whole frames without worrying about the receive buffer, offsets, partial receives, etc. The solution I chose is by no means a universal solution and I’m sure there could be some improvements.

How it Works

There is only one class and one interface in the library.

C#
public interface IFrameCalculator
{
bool CalculateFrameBoundary(byte[] data, out int frameLength);
}

The interface contains only one method. CalculateFrameBoundary is implemented by the client app as the boundary calculation strategy.

The developer can expect that the provided data will always contain at least the start of a frame. It is then up to the implementation to determine if the specified data contains a whole frame. If it does, the method returns true and the frameLength argument contains the length of the frame. If the provided data does not contain a whole frame, the method should return false with the value of frameLength being unimportant. This is all that the implementor should be concerned about in the implementation of this method.

C#
public sealed class Receiver
{
public Receiver(int receiveBufferSize, IFrameCalculator frameCalculator,
TcpClient tcpClient, Action<byte[], tcpclient=""> frameReceivedNotifier = null);

public TcpClient Client { get; }

public Action<byte[], tcpclient=""> FrameReceivedNotifier { get; }
}

The only constructor takes in the following:

  • receiveBufferSize – The size in bytes of the buffer to receive the data into. The smaller the buffer, the more “chatty” the receiving process will be.
  • frameCalculator – This is the implementation of IFrameCalculator to use to establish frame boundaries.
  • tcpClient – The TcpClient on which to start receiving.
  • frameReceivedNotifier – This is the method to call when a new frame has been identified and received.

From instantiation, the Receiver instance will start receiving data.

Any comments will be appreciated.

Thanks for reading.

Tagged: .net, beginreceive, c#, network programming, tcp, tcpclient

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead We Quote
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionWhy limit to TCP/IP ? Pin
sx200825-Apr-15 1:49
sx200825-Apr-15 1:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.