为什么设置 socket send/receive 缓冲区大小高于 sysctl max 时没有错误?

Why no error when setting socket send/receive buffer size higher than sysctl max?

为什么设置套接字 send/receive 缓冲区大小大于 sysctl max 时没有错误(正如我在下面演示的那样)? "expected behavior"?

没有错误

我的套接字 rmem_maxwmem_maxsysctl 值都设置为 212992:

net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
net.ipv4.tcp_rmem = 4096    87380   6291456
net.ipv4.tcp_wmem = 4096    16384   4194304
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
vm.lowmem_reserve_ratio = 256   256 32

当我创建套接字并尝试将套接字缓冲区大小设置为 64*1024*1024(大于 rmem_maxwmem_max 的值)时 send/receive:

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/format.hpp>

using boost::asio::ip::udp;
using boost::format;
using namespace std;

int main()
{
    try
    {
        boost::asio::io_service io_service;
        udp::socket socket(io_service, udp::endpoint(udp::v4(), 0));
        udp::resolver resolver(io_service);
        udp::resolver::query query(udp::v4(), "localhost", "7770");
        udp::resolver::iterator iterator = resolver.resolve(query);

        boost::system::error_code error_code;
        socket.set_option(boost::asio::socket_base::send_buffer_size(64*1024*1024), error_code);
        cout << error_code << endl;
        boost::asio::socket_base::send_buffer_size send_buffer_size;
        socket.get_option(send_buffer_size);
        cout << format("send_buffer_size=%s") % send_buffer_size.value() << endl;

        socket.set_option(boost::asio::socket_base::receive_buffer_size(64*1024*1024), error_code);
        cout << error_code << endl;
        boost::asio::socket_base::receive_buffer_size receive_buffer_size;
        socket.get_option(receive_buffer_size);
        cout << format("receive_buffer_size=%s") % receive_buffer_size.value() << endl;
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

我希望看到错误,但我没有收到任何错误:

system:0
send_buffer_size=212992
system:0
receive_buffer_size=212992

如果设置缓冲区大小不报错是"expected behavior"为setsockopt(),我猜适当的代码是总是在调用setsockopt()后检查值并提高我自己的错误或警告。

Why no error when setting socket send/receive buffer size higher than sysctl max (as I have demonstrated below)? is no error the "expected behavior"?

POSIX 没有明确说明。如果无法为有效选项设置指定值,它会隐式 permit setsockopt() 失败(返回 -1 并设置 errno),但是场景不在需要 实现失败的场景中。特别是,如果您参考 the specifications,您将不会在 setsockopt() 的失败条件列表中找到您的场景。最接近的似乎是 "The specified option is invalid at the specified socket level or the socket has been shut down," 但在指定的套接字级别 无效 只能应用于选项本身,而不是为其指定的值。

此外,its description of the receive buffer and send buffer options 将它们特别描述为 请求 以设置指定的缓冲区大小。例如:

The SO_RCVBUF option requests that the buffer space allocated for receive operations on this socket be set to the value, in bytes, of the option value. [...]

大多数其他选项的描述更具确定性,通常使用动词 "sets" 而不是 "requests"。也许我对它读得太多了,但对我来说,如果这是一个请求,那么实现不一定会遵守它。 setsockopt() 的成功是它是否交付请求的函数,而不是请求是否被兑现的函数。

您备注:

If setting the buffer size does not report an error is the "expected behavior" for the setsockopt(), I guess the appropriate code is to always check the value after calling setsockopt() and raise my own error or warning.

如果您希望报告 setsockopt() 未能设置您指定的确切缓冲区大小,那么您确实应该能够通过 getsockopt() 读回它们以进行检查。 POSIX 指定这些特定选项的值表示缓冲区大小字节;因此,在一致的实现中,提供给 setsockopt 的值与通过 getsockopt.

获得的值相当

然而,您可能仍然会感到惊讶。我可以想象出几个一致的变体,说明两者无法完全匹配是很常见的。