-1

我使用 C++ 开发了客户端服务器程序,所以我想接收超过 500kb 的数据,我的客户端消息以“!”终止 ,所以我想接收直到我的最后一个字节(!)接收,这是我的代码它不起作用。它有什么问题。

do
  {
  int num = recv(*csock,  buf, bytesLeft,0);

if (num == 0)
{
  break;
}
else if (num < 0 && errno != EINTR)
{
  fprintf(stderr, "Exit %d\n", __LINE__);
  exit(1);
}
else if (num > 0)
{
  numRd += num;
  buf += num;
  bytesLeft -= num;
  fprintf(stderr, "read %d bytes - remaining = %d\n", num, bytesLeft);
}

  }

    while (bytesLeft != 0);
   fprintf(stderr, "read total of %d bytes\n", numRd);
4

3 回答 3

6

虽然由于您的问题的措辞,我不确定您的问题到底是什么,但您通常不能使用strcat附加通过网络接收的原始缓冲区,除非您明确知道它们将以 NULL 终止,即使那样,那也不是如果您收到意外的数据传输,则真正“安全”。c-strings 的假设是它们是以 NULL 结尾的,但原始网络缓冲区可能不是,strcat如果输入缓冲区不是以 NULL 结尾的,使用将导致您过度运行输入缓冲区。代替strcat,使用一个已知的大小为 N 字节的固定大小的缓冲区来接收数据,并在缓冲区中增加一个临时指针,直到到达缓冲区的末尾或数据包传输的末尾。这样,您将始终从网络读取最多 N 个字节,并防止发生缓冲区溢出情况。

例如,您可以执行以下操作(由于所有复制,这不是最快或更有效的解决方案,但它有效):

unsigned char buf[10000];  //10Kb fixed-size buffer
unsigned char buffer[MAXRECV];  //temporary buffer

unsigned char* temp_buf = buf;
unsigned char* end_buf = buf + sizeof(buf);

do
{       
    iByteCount = recv(GetSocketId(), buffer,MAXRECV,0);   

    if ( iByteCount > 0 )
    {
        //make sure we're not about to go over the end of the buffer
        if (!((temp_buf + iByteCount) <= end_buf))
            break;

        fprintf(stderr, "Bytes received: %d\n",iByteCount);
        memcpy(temp_buf, buffer, iByteCount);
        temp_buf += iByteCount;
    }
    else if ( iByteCount == 0 )
    {
        if(temp_buf != buf)
        {
            //do process with received data
        }
        else
        {
            fprintf(stderr, "receive failed");
            break;
        }
    }
    else
    {
        fprintf(stderr, "recv failed: ");
        break;
    }
} while(iByteCount > 0 && temp_ptr < end_buf);  //check for end of buffer
于 2012-04-04T12:33:45.700 回答
1

您是否需要一个连续字节缓冲区中的所有 1MB+ 数据?如果是这样,并且您坚持使用终止“!”的协议 并且没有包含长度的标头,那么您会经常使用 memcpy() 和 realloc() 或其他一些缓冲区类型,例如 std::vector ,它们实际上只是做同样的事情。

如果您不需要一个字符串中的所有这些字节,则可以以其他方式存储它们,例如。*buffer 的向量,因此避免复制。

于 2012-04-04T12:47:12.970 回答
1

假设您使用的是阻塞套接字(这是套接字的默认模式),那么recv()将阻塞等待全部MAXRECV字节数到达。如果客户端发送的字节数少于该字节数,recv()将阻塞等待未到达的数据。

要解决此问题,您需要:

1)recv()使用 1 字节缓冲区调用,调用recv()直到遇到你的!字节。

2)在调用select()之前调用recv()以检测套接字何时实际有数据要读取,然后调用ioctlsocket(FIONREAD)以确定实际上可以在recv()没有阻塞的情况下读取多少字节,然后recv()读取该字节数。

于 2012-04-05T00:02:03.620 回答