I have 2 application that communicate over a network link. The sender will compress a packet using zlib's deflate() and send it over the network. The receiver will then decompress the data using inflate(). It is possible that packets will be lost over the network link; and in order to minimize decompression errors I have implemented the following approach:
Sender
calls deflate() with Z_SYNC_FLUSH most of the time, but intermittently calls deflate() with Z_FULL_FLUSH.
sends (along with the data) a 2-byte field that contains a bit indicating whether or not a FULL_FLUSH or SYNC_FLUSH was used and a sequence number.
Receiver
- Reads in the data; and using the sequence number, detects if a packet has been lost. When there is NO packet lost, the 2-bytes are removed and the decompression works properly.
When a packet lost is detected, the receiver checks whether or not the current packet is a FULL_FLUSH or a SYNC_FLUSH packet.
If it's a SYNC_FLUSH, then the packet is simply dropped and we proceed with the next packet.
If it's a FULL_FLUSH; however, the receiver removes the extra 2-byte and calls inflate().
This works 99% of the time; in the sense that the inflate() succeeds and the uncompressed data is indeed the same that the sender had before compression. This was my expectation!
Once in a while; however, this approach puts the receiver in a bad state where every subsequent packet (the FULL_FLUSH packet included) fails to decompress. inflate() returns a Z_DATA_ERROR and the zlibContext.zstream.msg contains 'incorrect header check'; although I have occasionally received a 'invalid distance too far back' message.
My first question is
Should I expect to recover and inflate() successfully when the packet at hand was compressed using a FULL_FLUSH flush mode; even if previous packets were lost? For example, sender compresses using
deflate(ctx, SYNC_FLUSH)
the first 3 packets and sends them; one at a time, over the network. The sender then compresses the fourth packet usingdeflate(ctx, FULL_FLUSH)
and sends it across the network. The receiver receives packet 1 & 2 and callsinflate()
with success. The receiver then receives packet 4; it detects (via the sequence #) that it has missed packet 3. Since packet 4 was compressed using a FULL_FLUSH, the receiver expects that theinflate()
will successfully decompress the packet. Is this a valid assumption?
My second question is
Is there anything else I need to do in in the receiver to be able recover from packet loss and continue decompressing packets?