In this case we would need some further reliability infrastructure at the "message" level. That is, we would need to buffer out-of-order messages until dropped messages arrive, and we would need to reject message duplicates in the instance that the original "dropped" packet eventually makes its way across the wire.
Yes, absolutely!
This is why there's typically several classes of delivery guarantee across different logical channels over a physical UDP connection:
- maybe delievered, maybe duplicated, maybe out of order -- implementation is to just deliver as soon as a packet comes in (this is least useful)
- maybe delivered, not duplicated, not out of order -- delivered assuming the incoming packet is later than the previous incoming packet (this is most useful)
- guaranteed delivery, not duplicated, maybe out of order -- each guaranteed message is delivered when the packet shows up, but de-duplicated if there's re-sends (lost acks)
- guaranteed delivery, not duplicated, not out of order -- this is similar to TCP, and requires the most buffering and state management
Only the last reliability type requires buffering actual messages on the receiving end; the others can make delivery decisions based only on sequence numbers (and, for the case of reliable, per-channel sequence numbers.)
Also, with reliable channels, you typically keep the reliability information on a per-message-channel basis, rather than a per-packet-stream basis.