c ++中读取函数的一个问题

che*_*eng 0 c++ sockets tcp

我使用读取函数从套接字读取数据,但是当数据超过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.当数据只有几百个字节时,读取功能按预期工作.

sel*_*bie 6

这是设计和预期的.

对您的问题的简短回答是,您应该继续调用"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的生活: