Search code examples
tcpomnet++inet

How can I receive exactly the same application data packets on a TCP data stream at the destination that was sent by the app at the source node


As a TCP connection is a stream, data traveling through the network is fragmented, buffered etc. during the transmission so there is no guarantee that the data will be delivered in the same packets to the destination application as was sent by source. I want to receive the data at the destination in exactly the same chunks as they were sent by the source app. Or in short term, how to properly implement TCP message framing in INET.


Solution

  • The trick is that you have to create a buffer at the application side and put all received data chunks into that buffer. There is a special queue class in INET (ChunkQueue) that allows you to queue received data chunks and merge those chunks automatically into a bigger chunk that was originally sent by the application layer at the other side.

    Practically you feed all the received data into the queue and you can ask the queue whether there is enough data in the queue to build up (one or more) chunk(s) that was sent by the application layer. You can use the queue's has() method to check whether at least one application layer data chunk is present and then you can get that out with the pop() method.

    Even better, there is a special callback interface (TcpSocket::ReceiveQueueBasedCallback) that can automatically put all the received chunks into a queue for you.

    If you implement that interface in your application, you just have to implement the socketDataArrived(TcpSocket *socket) method and check the queue content regularly (each time data arrives) to see whether enough data is present to be able to deliver the original chunks to the application. There is an example of this in the Ldp protocol implementation in INET:

    void MyApp::socketDataArrived(TcpSocket *socket)
    {
        auto queue = socket->getReceiveQueue();
        while (queue->has<MyAppMessage>()) {
            auto header = queue->pop<MyAppMessage>();
            processMyAppMessageFromTcp(header);
        }
    }