如何在UDP接收端读取数据报中的延迟并解决时延读取异常问题
Hey there! Let's tackle your UDP latency measurement problem head-on—those wonky timestamp values you're seeing are almost definitely a ByteBuffer indexing mix-up, so let's fix that and walk through how to properly read latency data on the receiver side.
First, Why You're Getting Those Weird Numbers
When you send a UDP packet with a sequence number followed by a timestamp, you're writing two distinct data types to the byte buffer: an int (4 bytes) for the sequence number, and a long (8 bytes) for the timestamp. If your receiver code reads these in the wrong order, or doesn't account for the byte offset of each field, it'll mash together bits from the sequence number and timestamp into a garbage long value—exactly like the 1498894798102 you're seeing.
Fixing the ByteBuffer Handling (Sender + Receiver)
Let's start with the correct way to package your data on the sender, then how to unpack it on the receiver.
Sender Code Example
Here's how to properly write the sequence number and timestamp to a ByteBuffer before sending:
// Initialize your UDP socket first (omitted for brevity) int sequenceNumber = 42; // Your incrementing sequence number long sendTimestamp = System.currentTimeMillis(); // Capture send time // Allocate buffer space: 4 bytes for int (seq) + 8 bytes for long (timestamp) ByteBuffer buffer = ByteBuffer.allocate(4 + 8); buffer.putInt(sequenceNumber); // Write sequence number first buffer.putLong(sendTimestamp); // Write timestamp second // Convert buffer to byte array for UDP packet byte[] packetData = buffer.array(); DatagramPacket packet = new DatagramPacket( packetData, packetData.length, InetAddress.getByName("receiver-ip"), 12345 // Replace with your receiver port ); datagramSocket.send(packet);
Receiver Code Example
Now, on the receiver side, you need to read the data in the exact same order you wrote it, and make sure you're only reading the actual bytes sent (not the entire receive buffer):
// Initialize UDP socket for receiving (omitted for brevity) byte[] receiveBuffer = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); datagramSocket.receive(receivePacket); // Wrap only the bytes that were actually received (critical!) ByteBuffer buffer = ByteBuffer.wrap( receivePacket.getData(), 0, receivePacket.getLength() ); // Read in the same order as sender: first sequence number, then timestamp int receivedSeq = buffer.getInt(); long receivedSendTimestamp = buffer.getLong(); // Calculate latency: current receive time minus sender's send time long receiveTimestamp = System.currentTimeMillis(); long latency = receiveTimestamp - receivedSendTimestamp; // Output results System.out.printf("Received sequence %d | Latency: %d ms%n", receivedSeq, latency);
Key Mistakes to Avoid
- Reading in the wrong order: If you call
getLong()beforegetInt()on the receiver, you'll read the first 8 bytes (which includes the 4-byte sequence number + first 4 bytes of the timestamp) as a long—this is exactly what's causing your weird values. - Not limiting the wrapped buffer length: Using
ByteBuffer.wrap(receiveBuffer)without specifying the actual packet length means you might read leftover bytes from previous packets, leading to corrupted data. - Mismatched data types: Make sure you're using
putInt()/getInt()for the sequence number (4 bytes) andputLong()/getLong()for the timestamp (8 bytes)—mixing these will throw off the byte offsets.
Bonus: Using Nanosecond Precision (If Needed)
If you want higher precision, swap System.currentTimeMillis() with System.nanoTime(). Just remember to convert the result to milliseconds (divide by 1_000_000) for readability, and keep everything as long to avoid overflow.
内容的提问来源于stack exchange,提问作者jakep

