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

谁都会走 提交于 2021-02-08 10:21:04

问题


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"?


My sysctl values for socket rmem_max and wmem_max are both set to 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:

#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.


回答1:


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 is not explicit about that. 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. In particular, if you refer to the specifications, you will not find your scenario on the list of failure conditions for 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. [...]

Most other options are described more deterministically, often with use of the verb "sets" instead of "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.

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.

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. POSIX specifies that the values of these particular options express the buffer sizes in bytes; therefore, on a conforming implementation, the values provided to setsockopt are comparable to those obtained via 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.



来源:https://stackoverflow.com/questions/46591712/why-no-error-when-setting-socket-send-receive-buffer-size-higher-than-sysctl-max

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!