我正在使用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);
....
}
我使用:
将内核缓冲区大小增加到1MBint buffsize = 1024*1024;
setsockopt(newsockfd, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof(buffsize));
并修改了sysctl变量:
sysctl -w net.core.rmem_max = 8388608; sysctl -w net.core.wmem_max = 8388608;
如此How to recive more than 65000 bytes in C++ socket using recv()所述,但没有任何改变。此外,我试图改变包装尺寸无济于事。
答案 0 :(得分:6)
你应该在{em>几个块中read
或recv
(一般来说;如果你运气不好,“几个”会变成“一个”)。因此,您需要管理缓冲并保留(并使用)接收的字节数。
所以在某些时候,你会编码
int nbrecv = recv(s, buffer + off, bufsize, 0);
if (nbrec>0) { off += nbrecv; bufsize -= nbrecv; }
你可能应该在你的event loop(通常在poll(2)左右...)中这样做。确实nbrec
比bufsize
少得多,您应该处理这种常见情况。
TCP不保证您将获得同一recv
中的所有字节!它可能取决于外部因素(路由,网络硬件......);它是面向流的协议,而不是消息包协议。如果您的应用程序需要消息,它应该根据内容缓冲输入到消息的输入和块。查看HTTP或SMTP:他们的消息具有明确定义的边界,由头信息(HTTP中为Content-Length:
)或结束约定(在SMTP中使用单个.
行)。
请仔细阅读read(2),recv(2),socket(7),tcp(7),部分sockets tutorial,Advanced Linux Programming。