简体   繁体   English

将套接字发送/接收缓冲区的大小设置为大于sysctl max时,为什么没有错误?

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

Why no error when setting socket send/receive buffer size higher than sysctl max (as I have demonstrated below)? 当将套接字发送/接收缓冲区的大小设置为大于sysctl max时,为什么没有错误(如下所示)? is no error the "expected behavior"? 错误是“预期行为”吗?


My sysctl values for socket rmem_max and wmem_max are both set to 212992: 套接字rmem_maxwmem_max sysctl值都设置为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

When I create a socket and try to set the socket buffer size to 64*1024*1024 (a value greater than the rmem_max and wmem_max ) for both send/receive: 当我创建一个套接字并尝试将套接字缓冲区的大小都设置为64 * 1024 * 1024(大于rmem_maxwmem_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;
}

I am expecting to see an error, but instead I don't get any errors: 我期望看到一个错误,但是我没有得到任何错误:

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

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()的“预期行为”,我猜合适的代码是在调用setsockopt()之后始终检查该值并引发我自己的错误或警告。

Why no error when setting socket send/receive buffer size higher than sysctl max (as I have demonstrated below)? 当将套接字发送/接收缓冲区的大小设置为大于sysctl max时,为什么没有错误(如下所示)? is no error the "expected behavior"? 错误是“预期行为”吗?

POSIX is not explicit about that. POSIX对此并不明确。 It does implicitly permit setsockopt() to fail (returning -1 and setting errno ) in the event that the specified value cannot be set for a valid option, but that scenario is not among those in which it requires implementations to fail. 如果无法为有效选项设置指定的值,则它确实隐式允许 setsockopt()失败(返回-1并设置errno ),但是这种情况不在要求实现失败的情况中。 In particular, if you refer to the specifications , you will not find your scenario on the list of failure conditions for setsockopt() . 特别是,如果您参考规范 ,则不会在setsockopt()的失败条件列表中找到您的方案。 The closest appears to be "The specified option is invalid at the specified socket level or the socket has been shut down," but being invalid at the specified socket level can only apply to the option itself, not the value specified for it. 最接近的显示是“指定的选项在指定的套接字级别无效或套接字已关闭”,但在指定的套接字级别无效只能应用于选项本身,而不能为其指定值。

Furthermore, its description of the receive buffer and send buffer options characterizes them in particular as requests to set the specified buffer sizes. 此外, 它对接收缓冲区和发送缓冲区选项的描述将它们的特征特别描述为设置指定缓冲区大小的请求 For example: 例如:

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

Most other options are described more deterministically, often with use of the verb "sets" instead of "requests". 大多数其他选项的确定性更高,通常使用动词“ sets”而不是“ requests”。 Perhaps I'm reading too much into it, but to me, if it's a request then the implementation is not bound to honor it. 也许我对它了解的太多了,但是对我来说,如果这是一个请求,那么实现并不一定会兑现它。 Success of setsockopt() is then a function of whether it delivers the request, not of whether the request was honored. 然后, setsockopt()成功取决于是否传递请求,而不取决于请求是否被接受。

You remark: 您备注:

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()的“预期行为”,我猜合适的代码是在调用setsockopt()之后始终检查该值并引发我自己的错误或警告。

If you wish to report failure of setsockopt() to set the exact buffer sizes you specify, then you should indeed be able to read them back via getsockopt() to check. 如果您希望报告setsockopt()无法设置您指定的确切缓冲区大小,那么您确实应该能够通过getsockopt()读回它们以进行检查。 POSIX specifies that the values of these particular options express the buffer sizes in bytes ; POSIX指定这些特定选项的值以字节表示缓冲区大小; therefore, on a conforming implementation, the values provided to setsockopt are comparable to those obtained via getsockopt . 因此,在符合标准的实现中,提供给setsockopt的值与通过getsockopt获得的值相当。

You might nevertheless be surprised, however. 但是,您可能会感到惊讶。 I can imagine several conforming variations on how it would be routine for the two to fail to match exactly. 我可以想象到两个一致的变化,这将是两个人无法完全匹配的例行程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM