The server app I am working on receives data over udp from my client app.
The server must receive udp data asynchronously. It appears there are two general ways to accomplish this.
Method 1:
boost::array<char, 65000> recv_buffer;
socket.async_receive_from(boost::asio::buffer(recv_buffer), senderEndpoint, handler);
Method 2 (from Variable-size buffer for receiving UDP packets):
socket.async_receive(boost::asio::null_buffers(), receive_handler);
// in the handler code
unsigned int available = socket.available();
buffer = resize_buffer_if_needed(available);
unsigned int packetSize = socket.receive_from(boost::asio::buffer(buffer, available), senderEndpoint, 0, ec);
Please help me evaluate the method that may be more apt for my needs. Regards.
Question 1:
From the mentioned post, it appears method 2 is inefficient as it causes asio to store the data into an internal buffer first and then copy it to my buffer. Is this correct?
Question 2:
The client will never send more than 64K of data in a single call to socket.send_to().
. Given this, is method 1 always a better choice?
Question 3:
I need to provide a way to reduce attacks on my server. I was thinking of using the first two bytes as a magic key. The idea is that I would ignore a message if the first two bytes are not the expected magic key. Given this, is it better to use method 2?
Question 4:
In my design, the next four bytes were going to be the actual size of the binary data that follows. However, given that socket.available()
already gives me the length, it appears I don't really have to send this information. Is it okay to simply rely on socket.available()
for the length?
No it doesn't store it in a temporary buffer first. It uses FIONREAD ioctl to see what is in the kernel's IP stack buffers.
I'd say yes, because the code is simpler and never needs to do any dynamic allocation
No, because you'll still receive whole packets at a time, which is the nature of datagram sockets. Just guard the maximum buffer size and avoid parsing untrusted data. A "magic number" is hardly any protection though. It's excruciatingly simple for an attacker to adapt (there's only 65536 possible combinations). Much better to have a HMAC-sgin (or similar) to authenticate the packet.
It's still UDP, so there's hardly any gain receiving in batches (the kernel doesn't so it's just more back-and-forth adding more CPU load for the same latency).
Also:
Q. In my design, the next four bytes were going to be the actual size of the binary data that follows
Beware of authentication first. Don't parse untrusted data. See Encrypt-then-MAC by Colin Percival
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments