There are a couple methods to improve netplay experience over a link with latency in the tens of milliseconds. Both are used by things like GGPO.
Adding constant lag
Send the input received from the local keyboard/gamepad immediately, but run the emulator a couple frames behind to allow input from other players to arrive.
If other players' input does not arrive in time, make the "dead reckoning"
assumption that the input hasn't changed. When the received input differs from the dead-reckoned input, rewind to the difference and re-emulate.
If you're relying on input sync to keep the players' emulated machines in sync, you want the reliable in-order delivery of TCP. This means that if you're using UDP to reach a server behind NAT
in cases where TCP traversal
doesn't work, you'll probably end up reimplementing most of TCP on top of UDP. Or do you instead require users to run their own server on a machine not behind NAT, such as a VPS leased from a hosting provider?