1

为什么将套接字发送/接收缓冲区大小设置为高于 sysctl max 时没有错误(如下所示)?“预期的行为”没有错误吗?


sysctl的套接字值rmem_maxwmem_max都设置为 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_maxand的值)时:wmem_max

#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

如果设置缓冲区大小不报告错误是 的“预期行为” setsockopt(),我想适当的代码是在调用后始终检查值setsockopt()并引发我自己的错误或警告。

4

1 回答 1

2

为什么将套接字发送/接收缓冲区大小设置为高于 sysctl max 时没有错误(如下所示)?“预期的行为”没有错误吗?

POSIX 没有明确说明这一点。在无法为有效选项设置指定值的情况下,它确实隐式允许 setsockopt()失败(返回 -1 和设置errno),但这种情况不属于需要实现失败的情况。特别是,如果您参考规范,您将不会在 的故障条件列表中找到您的场景setsockopt()。最接近的似乎是“指定的选项在指定的套接字级别无效或套接字已关闭”,但在指定的套接字级别无效只能应用于选项本身,而不是为其指定的值。

此外,它对接收缓冲区和发送缓冲区选项的描述将它们特别描述为设置指定缓冲区大小的请求。例如:

SO_RCVBUF 选项请求将为此套接字上的接收操作分配的缓冲区空间设置为选项值的值(以字节为单位)。[...]

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

你说:

如果设置缓冲区大小不报告错误是 的“预期行为” setsockopt(),我想适当的代码是在调用后始终检查值setsockopt()并引发我自己的错误或警告。

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

然而,你可能仍然感到惊讶。我可以想象有几个一致的变体,如果两者不能完全匹配,这将是例行公事。

于 2017-10-05T18:40:42.660 回答