macOS下setsockopt设置SO_SNDBUF报无效参数错误原因咨询
问题复现
main.cpp
#include <sys/socket.h> #include <string> #include <iostream> #include <unistd.h> int main() { int s; s = socket( AF_UNIX, SOCK_STREAM, 0 ); int val = 0; socklen_t size = (socklen_t)sizeof(val); if ( setsockopt( s, SOL_SOCKET, SO_SNDBUF, &val, size ) == -1 ) { std::cerr << "Set sock option failed" << std::endl; std::cerr << "Errno: " << errno << std::endl << "Error Message: " << std::strerror(errno) << std::endl; return -1; } return 0; }
编译命令
g++ main.cpp
运行结果
Set sock option failed Errno: 22 Error Message: Invalid argument
上述相同代码在Linux环境下可正常运行,但在macOS(10.15.7版本,编译环境为g++ Apple clang version 12.0.0)中运行会抛出上述错误。此外测试发现,设置SO_DEBUG等其他套接字选项时可正常执行。
问题原因
该错误是macOS与Linux内核的套接字实现逻辑差异导致的:
- macOS所用的XNU(Darwin)内核对
SO_SNDBUF、SO_RCVBUF两个套接字缓冲区选项设有硬性最小取值阈值(10.15版本下该最小值为256字节),不允许将缓冲区大小设置为0。代码中传入val=0不符合参数取值要求,内核做参数校验时直接返回EINVAL(错误码22,对应无效参数)。 - Linux内核对套接字缓冲区的最小值限制极低,允许传入0值,传入0时内核会触发对应特殊收发逻辑,因此不会报错。
SO_DEBUG这类开关型套接字选项仅接受0(关闭)、1(开启)两个合法入参,传入0属于合法操作,因此可以正常设置。
在macOS环境下调整套接字缓冲区大小时,传入的参数不能低于系统规定的最小值,无法实现和Linux一致的设置为0的效果。
内容的提问来源于stack exchange,提问作者Max Marcus
相关产品推荐
相关产品推荐

