Boost asio udp 读取优化问题
Boost asio udp read optimization questions
我正在处理的服务器应用程序通过 udp 从我的客户端应用程序接收数据。
服务器必须异步接收udp数据。似乎有两种通用方法可以完成此操作。
方法一:
boost::array<char, 65000> recv_buffer;
socket.async_receive_from(boost::asio::buffer(recv_buffer), senderEndpoint, handler);
方法二(来自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:
从提到的 post 来看,方法 2 似乎效率低下,因为它导致 asio 先将数据存储到内部缓冲区,然后再将其复制到我的缓冲区。这是正确的吗?
问题 2:
客户端绝不会在对 socket.send_to().
的单次调用中发送超过 64K 的数据。鉴于此,方法 1 总是更好的选择吗?
问题 3:
我需要提供一种方法来减少对我的服务器的攻击。我正在考虑使用前两个字节作为魔术键。这个想法是,如果前两个字节不是预期的魔术键,我会忽略一条消息。鉴于此,使用方法2更好吗?
问题 4:
在我的设计中,接下来的四个字节将是后面二进制数据的实际大小。但是,鉴于 socket.available()
已经给出了长度,看来我真的不必发送此信息。仅仅依靠 socket.available()
长度可以吗?
不,它不会先将其存储在临时缓冲区中。它使用 FIONREAD ioctl 查看内核的 IP 堆栈缓冲区中的内容。
我会说是的,因为代码更简单而且不需要做任何动态分配
不,因为您仍然会一次接收整个数据包,这是数据报套接字的特性。只需保护最大缓冲区大小并避免解析不受信任的数据。 "magic number" 几乎没有任何保护。攻击者适应起来非常简单(只有 65536 种可能的组合)。最好有一个 HMAC-sgin(或类似的)来验证数据包。
它仍然是UDP,所以几乎没有任何增益分批接收(内核没有所以它只是来回增加更多CPU负载以获得相同的延迟) .
还有:
Q. In my design, the next four bytes were going to be the actual size of the binary data that follows
首先要注意身份验证。不要解析不受信任的数据。参见 Colin PercivalEncrypt-then-MAC
我正在处理的服务器应用程序通过 udp 从我的客户端应用程序接收数据。
服务器必须异步接收udp数据。似乎有两种通用方法可以完成此操作。
方法一:
boost::array<char, 65000> recv_buffer;
socket.async_receive_from(boost::asio::buffer(recv_buffer), senderEndpoint, handler);
方法二(来自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:
从提到的 post 来看,方法 2 似乎效率低下,因为它导致 asio 先将数据存储到内部缓冲区,然后再将其复制到我的缓冲区。这是正确的吗?
问题 2:
客户端绝不会在对 socket.send_to().
的单次调用中发送超过 64K 的数据。鉴于此,方法 1 总是更好的选择吗?
问题 3:
我需要提供一种方法来减少对我的服务器的攻击。我正在考虑使用前两个字节作为魔术键。这个想法是,如果前两个字节不是预期的魔术键,我会忽略一条消息。鉴于此,使用方法2更好吗?
问题 4:
在我的设计中,接下来的四个字节将是后面二进制数据的实际大小。但是,鉴于 socket.available()
已经给出了长度,看来我真的不必发送此信息。仅仅依靠 socket.available()
长度可以吗?
不,它不会先将其存储在临时缓冲区中。它使用 FIONREAD ioctl 查看内核的 IP 堆栈缓冲区中的内容。
我会说是的,因为代码更简单而且不需要做任何动态分配
不,因为您仍然会一次接收整个数据包,这是数据报套接字的特性。只需保护最大缓冲区大小并避免解析不受信任的数据。 "magic number" 几乎没有任何保护。攻击者适应起来非常简单(只有 65536 种可能的组合)。最好有一个 HMAC-sgin(或类似的)来验证数据包。
它仍然是UDP,所以几乎没有任何增益分批接收(内核没有所以它只是来回增加更多CPU负载以获得相同的延迟) .
还有:
Q. In my design, the next four bytes were going to be the actual size of the binary data that follows
首先要注意身份验证。不要解析不受信任的数据。参见 Colin PercivalEncrypt-then-MAC