我正在使用以下代码测试功能 setsockopt(),我得到的行为我不明白: 下面是我正在运行的代码片段(在Ubuntu 12.04 64bit上编译,Qt 4.8.x ):
#include <QCoreApplication>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <QDebug>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int sock = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
int res;
int bufferSizeByte = QString(argv[1]).toInt();
qDebug() << "Setting socket buffer size to" << bufferSizeByte << "bytes";
res = setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (void*)&bufferSizeByte, sizeof(bufferSizeByte) );
if ( -1 == res )
{
qDebug() << "ERROR setting socket buffer size to" << bufferSizeByte << "bytes";
}
/*
* !! WARNING !!
* If we try setting the buff size over the kernel max: we do not get an error
*/
int readValue = 0;
unsigned int readLen = sizeof(readValue);
res = getsockopt( sock, SOL_SOCKET, SO_RCVBUF, (void*)&readValue, &readLen );
if ( -1 == res )
{
qDebug() << "ERROR reading socket buffer size";
}
else
{
qDebug() << "Read socket buffer size:" << readValue << "bytes";
Q_ASSERT ( readValue == bufferSizeByte*2 );
}
return a.exec();
}
基本上我正在设置套接字的recv缓冲区大小,并将其读回以验证操作是否真的成功。 将缓冲区大小设置为具有在Linux内核中配置的值( / proc / sys / net / core / rmem_max )的值会触发Q_ASSERT()为expecetd,但是我没有收到setsockopt错误消息
例如:
sergio@netbeast: sudo ./setsockopt 300000
Setting socket buffer size to 300000 bytes
Read socket buffer size: 262142 bytes
ASSERT: "readValue == bufferSizeByte*2" in file ../setsockopt/main.cpp, line 43
我没有得到的是为什么setsockopt()没有返回错误
有任何线索吗?
答案 0 :(得分:4)
sock_setsockopt()
的实现(这是系统调用setsockopt()
最终在内核中调用的内容)有一个注释,说明为什么设置太大的值不会导致错误。注释表明原因是为了与原始BSD实现兼容(因此,为BSD系统编写的软件更容易移植到Linux):
/* Don't error on this BSD doesn't and if you think
* about it this is right. Otherwise apps have to
* play 'guess the biggest size' games. RCVBUF/SNDBUF
* are treated in BSD as hints
*/
请注意,如果在执行此操作时未超过最大大小(并且已满足最小值),实际存储的内容是传递到SO_RCVBUF
的值的两倍。来自man page:
SO_RCVBUF
以字节为单位设置或获取最大套接字接收缓冲区。当使用setsockopt(2)
设置时,内核将此值加倍(以允许用于簿记开销的空间),并且getsockopt(2)
返回此加倍值。默认值由/proc/sys/net/core/rmem_default
文件设置,最大允许值由/proc/sys/net/core/rmem_max
文件设置。此选项的最小(加倍)值为256。