04_UDP

advertisement
User Datagram Protocol
UDP
UDP
Remember, UDP is the opposite of TCP
• Not reliable; data may be dropped
• No guarantee of in-order delivery
• Duplicate data is possible
• No built-in rate limiting
UDP
Why accept these limitations?
What happens if the network drops some data being
sent in TCP?
The receipt of data on the other application stops until
a time-out expires and the data is resent and
received
If we are sending continuous updates, this means all
data stops until the dropped data is resent and
received
UDP is usually lower latency than TCP, and has less
jitter
UDP
But what if we are sending position updates
every 1/30th of a second (frame rate?)
If one update gets dropped, another one is on
the way. What’s more, we’ll get the new
faster than if we go through a timeout-resend
cycle
What about duplicates and out-of-order? How
can you handle that?
Sequence Numbers
You can easily include a monotonically
increasing sequence number in your data
If you get a sequence number equal to or
before your last-received sequence number,
throw the packet away
Stream vs. Packets
TCP sockets are stream-oriented. You read or
sent a stream of bytes, like reading or writing
from a file. (InputStream, OutputStream)
UDP is packet-oriented. You compose discrete
packets or messages, then send them. (An
array of bytes, usually)
UDP packets can be big (up to 64K), but you
should keep them below 1500 bytes, better
512 bytes, for performance reasons. This is
usually easy to do.
Message Contents
In TCP it was best to use (or start with the assumption
of using) text, because it was universal and easy to
debug. But with numeric data we often have to
translate from text to binary
In UDP we are often dealing with data that is low
latency and numeric. Position updates, streaming
audio, streaming video, etc.
It usually makes sense to use binary data for this, but
this choice introduces all sorts of problems
Message Contents
Binary float and double value formats vary from
CPU to CPU and operating system to
operating system
The good news is that what a “float” or
“double” is is sort of standardized
The bad news is that byte order is not
Different CPUs may arrange the bytes in a float
in different ways
Byte Order
From least to most significant bit (integers)
1234
The same number may be represnted as
4321
On a different CPU
This is called “endian”, as in big endian or little
endian, a hangover from the elder days of
computing
Byte Order
Luckily, in Java these issues are taken care of for you
so long as you stick to the standard input and output
streams
If you work with C or other languages, this is not
necessarily taken care of for you, and you need to be
alert to the implications
But as long as it’s java on both ends, you will be OK,
and even if it’s not Java it may work by accident
In general, Intel CPUs use the opposite of the
“standard” network byte order
Protocols
How should we arrange the data? With text, we
could simply put it in some easily parsed text
format that we could also read
With binary, we need prior knowledge of how
the data is laid out, so we can read it
correctly. If the data isn’t read in the same
format as it was written, you’ll get garbage
Java Binary Data
ByteArrayOutputStream baos = new
ByteArrayOutputStream();
DataOutputStream dos = new
DataOutputStream(baos);
dos.writeFloat(17.0f);
dos.writeFloat(23.0f);
byte[] buffer = Baos.toByteArray();
Java Binary Data
The data is now in an array of bytes. This is
cross-platform, as long as the receiving side
knows the byte order
Floating Point Value 1
Floating Point Value 2
Binary Data
Reading is straightforward
ByteArrayInputStream bais = new
ByteArrayInputStream(buffer);
DataInputStream dis = new DataInputStream(bais);
float x = dis.readFloat();
Reading Data
What happens if you read an integer from the data
input stream instead of a float? A double instead of a
float?
This means that you need prior knowledge of what
format the data is in so you don’t get garbage out
It is a very good idea to have a protocol version number
in the first slot of the binary data
Usually a good idea to have a sequence number as well
UDP Sockets
You create UDP (or “datagram”) sockets in one
line. These are unconnected. With TCP, we
had a stream connection to another host.
With UDP it’s like an open mailbox that
anyone can drop messages into
DatagramSocket socket = new
DatagramSocket(4545);
Note no other IP, just the UDP port number
(which is distinct from the TCP port number)
Datagram Packets
The discrete messages being created are
DatagramPackets. These contain an address (the
port and IP of the machine they are being sent to)
and a payload. The payload is our binary data
byte[] buffer; …// fill out contents here
DatagramPacket packet = new
DatagramPacket(buffer, buffer.length,
ipAddress, port)
socket.send(packet);
Vs TCP
UDP is packet-oriented, TCP is stream-oriented
UDP is unreliable
UDP is not TCP! A common rookie mistake is to say “I
want to use UDP, but I also want it to be reliable”.
You then wind up creating a complex protocol that
re-invents TCP. Embrace the limitations of UDP
There can be some situations where you add TCP-like
capabilities to UDP, but you probably shouldn’t start
off that way
Rate Limiting
TCP automatically throttles back the sender if it
is overwhelming the receiver. Not so for UDP
Due to the nature of the software, even if the
sender and receiver have the same CPU
speed, the sender will at full rate overwhelm
the receiver. This means you need to be
careful that you don’t denial of service your
own software, which is the default behavior
unless you take steps to prevent it
Rate Limiting
Packets received at high rates fall off a cliff
Rec/sec
Packets Sent/sec
Data Loss
How do you handle losses of position updates?
How about streaming audio data?
• One solution is to include redundant data or
hamming codes in multiple packets. If one
packet gets lost you can recover the data
from other packets
Assignment
Write an application that sends, in binary
format, an entity identifier and position
Download