Another method is : on packets (with sequence ID used both directions) to include a Start ID+bitmap (like 32 bits) of the ACK status for a 'window' of the previously recieved packets in the sequence (with appropriate bit masks
/sequence /packet buffer chains maintained for the packet flow in each direction).
Thus every send has ACK data for a whole bunch of previous packets and unless something very bad is happening that ACK info should get through to be acted upon. You have the sender hold onto the unackknowledged packets to do resends (repeatedly if needed) on some delay schedule.
Again you watch the resend activity and if the whole connection is getting dodgy you start taking other contingencies to compensate (including calling upwards to the Application level for more drastic measures).
Likely you also have keep alive packets timed to be sent if there is no App data traffic, so the ACK bitmaps get throiugh and the programs can continuously monitor the connection status.
By that point you are replicating what many of the Reliable UDP libraries do (though a reason to roll your own is for added customizations for performance and added functionality ).