我使用读取函数从套接字读取数据,但是当数据超过4k时,读取函数只读取部分数据,例如,小于4k.这是关键代码:
mSockFD = socket(AF_INET, SOCK_STREAM, 0);
if (connect(mSockFD, (const sockaddr*)(&mSockAdd), sizeof(mSockAdd)) < 0)
{
cerr << "Error connecting in Crawl" << endl;
perror("");
return false;
}
n = write(mSockFD, httpReq.c_str(), httpReq.length());
bzero(mBuffer, BUFSIZE);
n = read(mSockFD, mBuffer, BUFSIZE);
Run Code Online (Sandbox Code Playgroud)
注意比BUFSIZE远大于4k.当数据只有几百个字节时,读取功能按预期工作.
这是设计和预期的.
对您的问题的简短回答是,您应该继续调用"read",直到获得所需的所有数据.那是:
int total_bytes = 0;
int expected = BUFSIZE;
int bytes_read;
char *buffer = malloc(BUFSIZE+1); // +1 for null at the end
while (total_bytes < expected)
{
int bytes_read = read(mSockFD, buffer+total_bytes, BUFSIZE-total_bytes);
if (bytes_read <= 0)
break;
total_bytes += bytes_read;
}
buffer[total_bytes] = 0; // null terminate - good for debugging as a string
Run Code Online (Sandbox Code Playgroud)
根据我的经验,最大的误解之一(导致错误),您将收到尽可能多的数据.我已经看到在真实产品中发送代码,期望套接字以这种方式工作(并且没有人确定为什么它不能可靠地工作).
当另一方发送N个字节时,您可能会很幸运并立即收到它.但是你应该计划在多个recv调用中分配N个字节.除了真正的网络错误之外,您最终将获得所有N个字节.分段,碎片,TCP窗口大小,MTU和套接字层的数据分块方案是所有这些的原因.当收到部分数据时,TCP层不知道还有多少未来.它只是将它所拥有的内容传递给应用程序.由应用决定它是否足够.
同样,"发送"呼叫可以聚集在同一个数据包中.
可能存在ioctls等会产生套接字阻塞,直到收到所有预期的数据.但我不知道有任何偏执.
另外,不要对套接字使用读写.使用recv并发送.
读这本书.它将改变你对套接字和TCP的生活: