Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

UDP is streams in the very classical definition: stream objects (bytes, probably, though a more faithful implementation would contain chunks/arrays) go out without predefined start/end. In other words, imagine that a single `read()` (or whatever) call returns random chunk from HTML source and it is your job to make sense of where in the space of whole page that chunk comes from. There is even no guarantee that consecutive read will return data "in order".

"File" abstraction layer has predefined start, end, length, order, and so on. You need some buffering magic layer on top of UDP that provides facilities mandated by file abstraction layer.



Worse, a socket read can return a UDP packet from any client as QUIC associates connections using 64-bit identifiers in the UDP payload, not using IP/port pairs. Ditto for the fact there can be multiple logical streams per connection. So any user space QUIC stack is responsible for routing packets for any particular connection and logical stream to the correct context using whatever bespoke API the stack provides.

IOW, with QUIC a file descriptor no longer represents a particular server/client connection, let alone a particular logical stream. From a server perspective, a user space QUIC stack is effectively equivalent to a user space TCP/IP stack. (Relatedly, user space QUIC server stacks are less CPU performant than HTTP stacks using TCP sockets, unless they use something like DPDK to skip the kernel IP stack altogether, avoiding the duplicative processing.)

The BSD Sockets API for SCTP (the original, non-UDP encapsulated version) permits 1-to-1 socket descriptors for associations--logical streams within a connection--in addition to an API for 1-to-many--1 socket descriptor representing a connection, over which you can use recvmsg/sendmsg to multiplex associations (logical streams). So you have 3 options for using SCTP from user space, from a dead simple, backwards compatible sockets API that matches how TCP/IP sockets work, to the low-level QUIC model where user space handles all routing and reassembly. I would expect kernel-based QUIC to work similarly, except combined with kernel-based TLS extensions, which is already a thing for TCP sockets.


> UDP is streams in the very classical definition

What do you mean exactly? UDP is not a stream protocol, it is an unreliable datagram one. A single read will return exactly one UDP datagram.

It is TCP where a read will return incremental data which is not necessarily aligned to what the other end wrote.

Of course QUIC builds a reliable stream abstraction on top of it, but that's not different from TCP.


In the classical definition stream is "sequence of data elements", without any additional guarantees. In this context TCP is stream transformer/filter: stream of "raw" packets is transformed into payload stream.

> What do you mean exactly? UDP is not a stream protocol, it is an unreliable datagram one. A single read will return exactly one UDP datagram.

This is exactly what makes UDP a stream of datagrams. Data is defined over one single UDP datagram - UDP gives exactly zero guarantees about data across datagram boundaries. There is no first, there is no last, there is no next/previous datagram, there no guarantees and expectations whether more datagrams will follow.

> Of course QUIC builds a reliable stream abstraction on top of it, but that's not different from TCP.

Key word "reliable", which is subset of streams. In goes stream of datagrams, out goes ordered (and otherwise identified) stream of bytes. Reading your comment it seems that you equate "stream" with "asynchronously fetched buffer" meaning from C++ and others, which is a stricter definition of streams.


I never heard of UDP defined as a stream (of packets), and it collides with the canonical definition of stream protocols from UNIX, BSD sockets, and the IP stack.


No, it does not collide with "canonical" (colloquial, I'd say) definition of streams, when you think about it. It's only a matter of guarantees on a stream. It is not buffered reads/writes that make a stream.

I can take a bunch of XMLs, "stream" them into a TCP socket on one end, feed that socket to "XML stream processing library" on another end and... Watch it blow up, because apparently the only streamy thing about the library is that it can handle asynchronously filled buffer, but will nevertheless blow up if fed anything but a single well-formed xml ¯\_(ツ)_/¯


It is not colloquial when talking about network protocols. From socket(2):

          SOCK_STREAM
              Provides sequenced, reliable, two-way, connection-based
              byte streams.  An out-of-band data transmission mechanism
              may be supported.
Not sure what your reference to buffering or async buffers and XML has to do with the topic.


Here you go, right in the documentation you get that TCP streams are streams with additional qualifiers. Not simply streams. The whole thing we are arguing about: TCP streams are subset of streams.

> Not sure what your reference to buffering or async buffers and XML has to do with the topic. An illustrative point for what happens when assumptions from a contrived case are applied on a more relaxed case.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: