The old modem protocols XModem, YModem and Zmodem are designed for what you are doing they send packets with CRC checks and packets are accept or reject which causes the packet to be resent. You can net search for the code.
A simple XModem send routine looks like this which should give you an understanding of what it does
Send data of a fixed packet size, send the CRC for the packet .. wait for ACK or NAK. Resend packet on NAK. simple xmodem/ymodem implementation in C · GitHub[^]
A full Zmodem with both send and receive implementation is more complex but once you understand the simple xmodem it should make sense. The greater complexity is because the transfer packet size auto adjusts, as you get more packet rejects it sends smaller and smaller packets. If you are getting transmission errors you don't want to waste time sending large packets over and over, expect an error and send small packets. The smaller packets means there is a lot of packet acknowledges going on but that is faster than resending large packets. pkg-sbbs/zmodem.c at master · ftnapps/pkg-sbbs · GitHub[^]
Ethernet protocols extend beyond that in that they allow and expect the packets to arrive out of order. The X/Y/Z modem protocols are strictly packets in order processes which is what you said was okay.
A little while ago, I paid a visit to the official documentation page that covers the LTCG linkage editor command line switch, at /LTCG (Link-time Code Generation) | Microsoft Docs, which spears to me to give misleading information about where the option is set in Visual Studio. Being the good citizen that I am, I wrote it up, which gave rise to Setting LTCG in Visual Studio 2017 · Issue #376 · MicrosoftDocs/cpp-docs · GitHub. Upon visiting the generated issue page on GitHub, I added a picture of the property page where I found and set the option, to expedite linking of the release build of a project that imports a module that was compiled with the /GL switch, so that it can be used with P/Invoke.
This is not my first exposure to commenting on Microsoft documentation, and I am delighted to see this direct feedback channel. I wish there had been such a direct channel when I discovered a bug in the COBOL compiler for the IBM System/34, way back in 1980. I reported that bug, but it required writing and sending a full-blown business letter, via the United States Postal Service, and the attendant delays and labor on the IBM end of the connection.
I was further gratified to discover that, since I have an active GitHub account, I could augment the textual comment that caused the issue to be opened with a picture of my screen, captured courtesy of the ALT-Print Screen keyboard shortcut and the built-in Paint program. Yes, I still use Paint, more often than you might think.
Since I assume that adding such detail to the issue is available to me because I have an active GitHub account, I'd say this is ample reason for any serious developer to have one, even if you don't have any repositories, although I opened it because I have a handful of them.
David A. Gray
Delivering Solutions for the Ages, One Problem at a Time
Interpreting the Fundamental Principle of Tabular Reporting