In the context of a UDP Message that I receive the UDP Message will have apart from the header containing the size of the overall packet, the second field is an unsigned int indicating a sequence number. The rest of packet is PayLoad [ actual message(s) ].
The payload contains zero or more messages which need to be further decoded and parsed. Now there is the below requirement in design.
"Messages can straddle packet boundaries."
What does this sentence mean in layman terms?
This might be quite simple. A message is thought not to be the same as a packet, and the former may be scattered across multiple packets.
Say, the first part of the message may reside in the first packet whilst the rest of it in the second.
Related
This question was closed on the Networking SE because "questions about protocols above OSI layer-4 are off-topic here" so I'm trying here.
This may be a silly question, but if in QUIC we maintain separate sliding windows for each stream, why is there a need for sequencing even below the stream level?
It seems to me that an application will not receive the same data twice because we already sequence streams by themselves, and we also can acknowledge each stream separately without sequencing the packets themselves.
I presume you mean packet number, as there isn't a sequence number as such in QUIC.
If so, then the packet number used in QUIC performs a number of roles, such as being used within the ACK process, sequencing at the packet level, and also is used as part of the nonce input into the AEAD encryption process.
From https://datatracker.ietf.org/doc/html/rfc9001 5.3 AEAD
The nonce, N, is formed by combining the packet protection IV with the packet number.
From https://datatracker.ietf.org/doc/html/rfc9000 13.2.3. Managing ACK Ranges
A receiver SHOULD include an ACK Range containing the largest received packet number in every ACK frame.
So I'm reading trying to find more about sockets and I found that the documentation kind of repeats itself without going in any further detail in regards to the way sockets send data:
So what does the {packet, N} do when specifying this in the options (when opening a socket) ? Does it include a header of N bytes before the data or does it break the message into N packets? Or does it include a header of N to all the packets that the message ends up being broken into?
I was reading Joe Armstrong's Software for a concurrent world and I found this paragraph:
The word packet refers to the length of an application request or response message, not to the physical packet seen on the wire.
I can't get my head round the meaning of this. What is meant by the packet seen on the wire.
I tried to look into the documentation and I found little referring to what the option does. The brief explanation that I found is that it prepends the message with a N header however I also found this comment in a code written as an example:
%% Usually, it's a good idea to give up in case of a
%% send timeout, as you never know how much actually
%% reached the server, maybe only a packet header?!
According to this, then, the message gets broken into pieces (a random number I presume?) and each gets sent with a N byte header.
My question is how does the {header, N} option affect the way data is sent.
The excerpt from Joe's book you quote refers to the fact that applications are typically blissfully unaware of how networks arrange data for transmission. Depending on the network type, configuration, and protocols in use, the blocks of data sent over it will vary in size and will be framed with different metadata. Applications typically don't see raw packets, framing information, or the fact that sometimes raw packets are retransmitted due to problems that cause them to be dropped or corrupted.
Your question mentions two options: {packet, N} and {header, N}. These are quite different from each other.
The {packet, N} option allows N to be 1, 2, or 4. It attaches a header of N bytes to the front the message. The header specifies, in network order, the length of the message, i.e. the number of bytes in the message.
If you send a message consisting of X bytes, Erlang will prepend to the data N bytes containing the network order value of X, and send the whole thing. Assuming the receiver has also been configured with the same {packet, N} option, it will read the N-byte header to determine how many bytes to expect, wait to receive that many bytes, and then deliver those bytes, without the length header, to the receiving application. How the underlying networking software and hardware breaks the data into chunks for transmission across the network is a separate matter hidden from your application.
The {header, Size} option delivers the message to the receiver as a list of Size bytes followed by the remainder of the data as a binary. This option makes sense only when the binary option is in effect for the socket.
I know that for TCP you can have for example Nagle's Algorithm enabled. However, can you have something similar for UDP?
Practical Question(assume UDP socket):
If I call send() two times in a short period of time with 1 byte of data in each send() call. Is it possible that the transport layer decides to send only 1 UPD packet with the 1 byte + 1 byte = 2 bytes of data?
Thanks in advance!
No. UDP datagrams are delivered intact exactly as sent, or not at all.
Not according to the RFC (RFC 768). Above IP facilities themselves, UDP really only provides, as extras, port-based routing and a little bit of extra detection for corruption or misrouting.
That means there's no facility to combine datagrams. In fact, since it's meant to be transaction oriented, I would say that combining two transactions into one may well be a bad idea in terms of keeping these transaction disparate.
Otherwise, you would need a layer above UDP which could figure out how to extract these transactions from a datagram. At the moment, that's not necessary since the datagram is the transaction.
As added support (though not, of course, definitive) for this contention, see the UDP wikipedia page:
Datagrams – Packets are sent individually and are checked for integrity only if they arrive. Packets have definite boundaries which are honored upon receipt, meaning a read operation at the receiver socket will yield an entire message as it was originally sent.
However, the best support for it comes from one of its clients. UDP was specially engineered for TFTP (among other things) and that protocol breaks down if you cannot distinguish a transaction.
Specifically, one of the TFTP transaction types is the data transaction which consists of an opcode, block number and up to 512 bytes of data. Without a length indication at the start or a sentinel value at the end, there is no way to work out where the next transaction would start unless there is a one-to-one mapping between transaction and datagram.
As an aside, the other four TFTP transaction types have either a fixed length or end-of-string sentinel values but the data transaction is the decider here.
I know that it is possible that multiple packets would be stacked to the buffer to be read from and that a long packet might require a loop of multiple send attempts to be fully sent. But I have a question about packaging in these cases:
If I call recv (or any alternative (low-level) function) when there are multiple packets awaiting to be read, would it return them all stacked into my buffer or only one of them (or part of the first one if my buffer is insufficient)?
If I send a long packet which requires multiple iterations to be sent fully, does it count as a single packet or multiple packets? It's basically a question whether it marks that the package sent is not full?
These questions came to my mind when I thought about web sockets packaging. Special characters are used to mark the beginning and end of a packet which sorta leads to a conclusion that it's not possible to separate multiple packages.
P.S. All the questions are about TCP/IP but you are welcomed to share information (answers) about UDP as well.
TCP sockets are stream based. The order is guaranteed but the number of bytes you receive with each recv/read could be any chunk of the pending bytes from the sender. You can layer a message based transport on top of TCP by adding framing information to indicate the way that the payload should be chunked into messages. This is what WebSockets does. Each WebSocket message/frame starts with at least 2 bytes of header information which contains the length of the payload to follow. This allows the receiver to wait for and re-assemble complete messages.
For example, libraries/interfaces that implement the standard Websocket API or a similar API (such as a browser), the onmessage event will fire once for each message received and the data attribute of the event will contain the entire message.
Note that in the older Hixie version of WebSockets, each frame was started with '\x00' and terminated with '\xff'. The current standardized IETF 6455 (HyBi) version of the protocol uses the header information that contains the length which allows much easier processing of the frames (but note that both the old and new are still message based and have basically the same API).
TCP connection provides for stream of bytes, so treat it as such. No application message boundaries are preserved - one send can correspond to multiple receives and the other way around. You need loops on both sides.
UDP, on the other hand, is datagram (i.e. message) based. Here one read will always dequeue single datagram (unless you mess with low-level flags on the socket). Event if your application buffer is smaller then the pending datagram and you read only a part of it, the rest of it is lost. The way around it is to limit the size of datagrams you send to something bellow the normal MTU of 1500 (less IP and UDP headers, so actually 1472).
Can anybody explain how the packet interaction with TCP Selective Acknowledgment works?
I found the definition on Wikipedia, but I cannot get a clear picture what Selective Acknowledgment really does compared to Positive Acknowledgment and Negative Acknowledgment.
TCP breaks the information it sends into segments... essentially segments are chunks of data no larger than the current value of the TCP MSS (maximum segment size) received from the other end. Those chunks have incrementing sequence numbers (based on total data byte counts sent in the TCP session) that allow TCP to know when something got lost in-flight; the first TCP sequence number is chosen at random, and for security-purposes it should not be a pseudo-random number. Most of the time, the MTU of your local ethernet is smaller than the MSS, so they could send multiple segments to you before you can ACK.
It is helpful to think of these things in the time sequence they got standardized...
First came Positive Acknowledgement, which is the mechanism of telling the sender you got the data, and the sequence number you ACK with is the maximum byte-sequence received per TCP chunk (a.k.a segment) he sent.
I will demonstrate below, but in my examples you will see small TCP segment numbers like 1,2,3,4,5... in reality these byte-sequence numbers will be large, incrementing, and have gaps between them (but that's normal... TCP typically sends data in chunks at least 500 bytes long).
So, let's suppose the sender xmits segment numbers 1,2,3,4,5 before send your first ACK. If all goes well, you send an ACK for 1,2,3,4,5 and life is good. If 2 gets lost, everything is on hold till the sender realizes that 2 has never been ACK'd; he knows because you send duplicate ACKs for 1. Upon the proper timeout, the sender xmits 2,3,4,5 again.
Then Selective Acknowledgement was proposed as a way to make this more efficient. In the same example, you ACK 1, and SACK segments 3 through 5 along with it (if you use a sniffer, you'll see something like "ACK:1, SACK:3-5" for the ACK packets from you). This way, the sender knows it only has to retransmit TCP segment 2... so life is better. Also, note that the SACK defined the edges of the contiguous data you have received; however, multiple non-contiguous data segments can be SACK'd at the same time.
Negative Acknowledgement is the mechanism of telling the sender only about missing data. If you don't tell them something is missing, they keep sending the data 'till you cry uncle.
HTH, \m