我正在处理的服务器应用程序通过我的客户端应用程序从udp接收数据。
服务器必须异步接收udp数据。看来有两种方法可以实现这一目标。
方法1:
boost::array<char, 65000> recv_buffer;
socket.async_receive_from(boost::asio::buffer(recv_buffer), senderEndpoint, handler);
方法2(来自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);
请帮我评估一下可能更符合我需求的方法。问候。
问题1:
从上面提到的帖子看来,方法2效率很低,因为它会导致asio首先将数据存储到内部缓冲区,然后将其复制到我的缓冲区。这是对的吗?
问题2:
客户端在socket.send_to().
的一次通话中永远不会发送超过64K的数据。鉴于此,方法1总是更好的选择吗?
问题3:
我需要提供一种方法来减少对我的服务器的攻击。我在考虑将前两个字节用作魔术键。我的想法是,如果前两个字节不是预期的魔术键,我会忽略一条消息。鉴于此,使用方法2是否更好?
问题4:
在我的设计中,接下来的四个字节将是随后的二进制数据的实际大小。但是,鉴于socket.available()
已经给出了我的长度,看来我真的不必发送这些信息。是否可以简单地依赖socket.available()
的长度?
答案 0 :(得分:2)
不,它不会先将它存储在临时缓冲区中。它使用FIONREAD ioctl来查看内核的IP堆栈缓冲区中的内容。
我会说是的,因为代码更简单,从不需要进行任何动态分配
不,因为您仍然会一次收到整个数据包,这是数据报套接字的本质。只需保护最大缓冲区大小,避免解析不受信任的数据。虽然“神奇数字”几乎没有任何保护。对于攻击者来说,这是非常简单的适应(只有65536种可能的组合)。使用HMAC-sgin(或类似的)来验证数据包要好得多。
它仍然是UDP,所以批量接收几乎没有任何收益(内核不会这样,只是为了相同的延迟而更多地来回添加更多CPU负载)。
此外:
Q值。在我的设计中,接下来的四个字节将是后面的二进制数据的实际大小
首先注意身份验证。不解析不受信任的数据。见Colin Percival的Encrypt-then-MAC