setsockopt() 在设置大套接字 recv 缓冲区时不返回错误
setsockopt() not returning error when setting a big socket recv buffer
我正在使用以下代码测试函数setsockopt(),我得到了一个我不明白的行为:以下是我正在运行的代码片段(在 Ubuntu 12.04 64 位、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() 不返回错误
有什么线索吗?
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
的值的两倍。从手册页:
SO_RCVBUF
设置或获取最大套接字接收缓冲区(以字节为单位)。当使用setsockopt(2)
设置时,内核会加倍此值(以留出记账开销的空间),并且此加倍值由getsockopt(2)
返回。默认值由/proc/sys/net/core/rmem_default
文件设置,允许的最大值由/proc/sys/net/core/rmem_max
文件设置。此选项的最小(双倍)值为 256。
相关文章:
- 从返回的顶点缓冲区查询顶点结构
- openCL-创建子缓冲区返回错误代码13
- std::ifstream.read() 不会向我的缓冲区返回任何内容
- 返回指向矢量数据的指针,而不复制缓冲区和内存泄漏
- TCP 服务器/客户端:客户端 recv() 返回空白缓冲区
- 从C 中的函数中动态分配的缓冲区返回的最佳模式是什么?
- InternetReadFile 填充缓冲区,但返回零字节读取
- c++winsock-recv()返回不正确且奇怪的缓冲区
- Sample Grabber返回的IMediaSample具有意外的缓冲区大小
- 从缓冲区指针计算堆栈中的返回地址
- HidD_GetManufacturerString和类似的函数返回成功,但不修改缓冲区
- zlib 膨胀返回缓冲区错误
- waveOutWrite 缓冲区永远不会返回到应用程序
- C++使用缓冲区写入文本时,在文件末尾返回非 ASCII 字符
- setsockopt() 在设置大套接字 recv 缓冲区时不返回错误
- 为什么_splitpath_s()使用自定义大小的字符串缓冲区来返回驱动器号
- 链表缓冲区;应该插入什么返回
- GetUserNameEx()返回的缓冲区的大小
- 如何在c++中限制缓冲区大小并返回缓冲区限制?
- GetCurrentDirectory 缓冲区不返回正确的值