如何使用read()在C++套接字中接收超过40Kb

Moh*_*HME 1 c++ sockets buffer

我正在使用C++在Linux中开发客户端 - 服务器应用程序(TCP).该应用程序负责测试网络性能.客户端和服务器之间的连接只建立一次,然后使用write()/read()自己定义的协议发送/接收数据.

当数据超过40Kb时,我只收到一部分数据.(即我收到约48KB)

请找到代码的相关部分:

while (1) {
        servMtx.lock();
        ...
        serv_bytes = (byte *) malloc(size_bytes);
        n = read(newsockfd, serv_bytes,size_bytes);
        if (n != (int)size_bytes ) {
            std::cerr << "No enough data available for msg. Received just: " << n << std::endl;
            continue;
        }
        receivedBytes += n + size_header_bytes + sizeof(ssize_t);
        ....
}
Run Code Online (Sandbox Code Playgroud)

我使用以下内容将内核缓冲区大小增加到1MB:

int buffsize = 1024*1024;
setsockopt(newsockfd, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize)); 
Run Code Online (Sandbox Code Playgroud)

和修改过的sysctl变量:

sysctl -w net.core.rmem_max = 8388608; sysctl -w net.core.wmem_max = 8388608;

如上所述如何使用recv()在C++套接字中恢复超过65000个字节但没有任何改变.此外,我试图改变包装尺寸无济于事.

Bas*_*tch 6

你应该read还是recv几个块中(一般;如果你运气不好,有"几个"变成"1").因此,您需要管理缓冲并保留(并使用)接收字节的数量.

所以在某些时候,你会编码

int nbrecv = recv(s, buffer + off, bufsize, 0);
if (nbrec>0) { off += nbrecv; bufsize -= nbrecv; }
Run Code Online (Sandbox Code Playgroud)

你可能应该在事件循环中这样做(通常在poll(2)周围......).它确实发生nbrec了很多bufsize,你应该处理这种常见情况.

TCP不保证你将获得相同的所有字节recv!它可能取决于外部因素(路由,网络硬件......); 它是面向流的协议,而不是消息包协议.如果您的应用程序需要消息,它应该根据内容缓冲输入到消息的输入和块.查看HTTPSMTP:它们的消息具有由头信息(Content-Length:在HTTP中)或通过结束约定(.在SMTP中具有单个行)给出的明确定义的边界.

请仔细阅读read(2),recv(2),socket(7),tcp(7),一些套接字教程,高级Linux编程.