Again, the point is not to call UDP reliable, it's that it doesn't make sense for the reasons I stated above. If you choose the wrong tool for a usecase then the communication channel will be unreliable in either case. There's a lot of confusion about this -- it is valid to call a communication channel unreliable for the system to respond accordingly, not the protocol itself.
The only real guarantee that TCP provides is in-order delivery. That is, it really guarantees that if you sent two requests A and B to a server, the server will never see request B unless it saw request A first. Again looking at HTTP, this is why request pipelining theoretically works without including any request ID in the response: the client knows that if it sent reqA first and reqB second, the first response it gets from the server will be respA, and the second will be respB (if either of them ever arrives, of course).
Note that the fact ACK is not shown to the application layer is not an implementation limitation, it is a fundamental part of the design of TCP. The ACK is generated by the TCP stack once the packet was received. This doesn't guarantee in any way that the application will ever see this packet: the application could crash, for example, and never receive (and thus act on) this message. The in-order guarantee works instead because the transport layer can simply avoid ever showing reqB to the application layer if it knows that there was a reqA before it that it didn't receive. So the transport can in fact ensure that it's impossible for the application to see out-of-order data, but it can't ensure that the application has actually received any data.
I don't, nor do I think it is unreliable. Protocols exist in an abstract space, but they are instantiated in a system that works within physical /constraints/ (noise, faults, oxidation, etc.). These constraints vary because different systems work in different environments.
The systems we make also have to provide utility for the /purposes/ that it's made. Reliability is necessary to trust the utility of a system.
If I'm playing a multiplayer FPS game and due to backoff I see players snapping back to the position of a lost packet once it is received, I will not think that the game is reliable (and I will be especially sad since this is known issue with known improvements).
If I don't care about old packets and only care about the latest packet, I don't work with old information -- but the information is incomplete. Latency will still be noticeable on a noisy connection, but my brain can at least anticipate -- guess where to look next -- once the last packet is received.
That incomplete information can be used to extrapolate movements. So the final step is to use a model to predict movements in (short) moments when a packet is not received. You can't do this when the information isn't relevant anymore. When that's done, I -- the player -- will feel like that game is more reliable than the first TCP case.
(Games, and real-time interfaces in general, have some interesting aspects that I think is well covered in Game Feel by Steve Swink).
Either that or it's slop that somehow made it to the front page.
I never said UDP wasn’t sometimes fit for purpose. I said it’s unreliable compared to TCP. Those are not the same statement. Sometimes reliability isn’t part of the spec, so you do without that or build your own reliability around it if the less reliable option is still a better fit.
This is common in the industry, actually. The ‘I’ in RAID stands for inexpensive, because it’s a redundant array. We scale horizontally these days where we can because more cheaper servers can sometimes scale further and more reliably than fewer more premium servers. Heck, a paper cup is unreliable compared to ceramic or stainless steel, but Starbucks and Tim Horton’s move a lot of product in them.
My understanding is that in Linux, TCP on localhost (including packets sent to a public address on a local interface) bypasses the stack; I don't see why it would be a problem for UDP to do the same.
This is contrast with FreeBSD, where TCP to localhost is actually packetized and queued on the loopback interface, and you can experience congestion collapse on loopback if you do things right(wrong).
UDP over the network does not on its own guarantee packet retries or proper delivery order. How reliable is that?
UDP on Linux to localhost or hair-pinned between two public IPs on the same host can result in reordered packets when the kernel is busy with a lot of traffic or the CPU is context switching enough. It happens when a UDP queue is handled by a certain core and gets swapped to another. I’ve had to set up two machines with a cable between them because the ordering is actually more stable than over localhost. A colleague is working on a kernel patch to bypass part of the UDP stack to restore proper ordering, which will probably need to be maintained in-house or at least hidden behind a kernel config knob upstream since this reordering is considered acceptable under the guarantees for UDP. How reliable is that?
So, yeah, you can say UDP is reliable but compared to TCP or QUIC it actually really isn't.