客户端读取的字节数少于Server在套接字上发送的字节数

时间:2012-12-06 23:58:45

标签: c sockets

我的服务器代码如下:

while(bytes_written < filesize){
                    //Send from send_ptr
                    bw = send(child_socket, send_ptr, newLength, 0);
                    printf("%d bytes written\n", (int)bw);
                    //Increment bytes written
                    bytes_written += bw;
                    //Move send pointer
                    send_ptr = send_ptr + bw;
}

我的客户端代码如下:

while((num_bytes_recv = read(sd, jpgBufferPointer, BUFFER_LENGTH))>0){
        total_bytes_recv += num_bytes_recv;
        printf("Read %d bytes\n",num_bytes_recv);

        //Check for error
        if(jpgError == NULL)
            jpgError = strstr(jpgBufferPointer, "404 Not Found");

        if(jpgError != NULL){
            //Forwarding error response
            if(send(sd, jpgBuffer, num_bytes_recv, 0) == -1){
                error("Failed to send response message to client"); 
            }
        }   
        else{
            //Find content size
            contentSizeBuffer = strstr(jpgBufferPointer,"Content-Length");

            if(contentSizeBuffer != NULL){
                contentSizeBuffer=contentSizeBuffer+16;
                contentSize=atoi(contentSizeBuffer);                    
                jpgBuffer=(char*)realloc(jpgBuffer,(contentSize+FILE_NAME_LENGTH*2)*sizeof(char));
                jpgBufferPointer=jpgBuffer;
            }
            jpgBufferPointer+=num_bytes_recv;
        }
    }

服务器说它已经发送了所有43000个字节,但是客户端说它只收到了32768个字节。

感谢任何帮助!感谢

3 个答案:

答案 0 :(得分:2)

你在发送部分有一个错误,你应该更新newLength,因为如果你还剩1个字节要从文件中发送,它会发送更多,从你要发送的内容存储的内存区域出来。你应该这样修理:

bw = send(child_socket, send_ptr, newLength<(filesize-bytes_written)?newLength:(filesize-bytes_written), 0);

通过这种方式,最后一次发送将具有正确的大小。

另外,如果您没有使用任何标志,请使用write而不是send。

答案 1 :(得分:0)

您需要在读取端具有与写入侧(bytes_written&lt; filesize)相似的循环(即,当您可以读取更多字节时,您应该读取它们并附加它们。)

网络不保证一次read()调用将返回所有可用数据。

答案 2 :(得分:0)

编写客户端 - 服务器套接字编程的最佳方法是在数据之前设置标头。标头应说明要传输的数据量。

例如,要发送数据“Hello World”,请将其发送为“0011 + HELLO WORLD”

此处11表示发件人现在计划发送的数据大小。读取前4个字节的接收器可以理解他应该准备好从发送器读取下一个11字节的数据。

所以读者会做两读:      hRead = 5 / * 5表示它可以从数据中读取最多9999个字节。      读(sd,buff,hRead);      dRead = atoi(buff);      readn(sd,buff,dRead);

例如:服务器

 size_t sendn(int fd, const void *vptr, size_t n) {
   size_t nleft;
   size_t nwritten;
   const char *ptr;

   ptr = vptr;
   nleft = n;
   while (nleft > 0) {
       if ((nwritten = send(fd, vptr, nleft, 0)) <= 0) {
          if (errno == EINTR)
               nwritten = 0;
          else {
              fprintf(stderr, "send failed  %d - %s\n", fd, strerror(errno));
              return (-1);
          }
        }
        nleft -= nwritten;
        ptr += nwritten;
   }
   return (n);
  }

发送消息:

  sprintf(buff, "%d + %d + %s\r\n", MSG_LOGIN, strlen("Hello World"), Hello World);
  sendn(sd, buff, strlen(buff));

客户:

 size_t readn(int fd, void *vptr, size_t n) {
  size_t nleft;
  size_t nread;
  char *ptr;

  ptr = vptr;
  nleft = n;
  while (nleft > 0) {
      if ((nread = recv(fd, ptr, nleft, 0)) < 0) {
          if (errno == EINTR)
              nread = 0;
          else {
              fprintf(stderr, "read failed %d - %s\n", fd, strerror(errno));
              return (-1);
          }
      } else if (nread == 0)
          break;

      nleft -= nread;
      ptr += nread;
  }
  return (n - nleft);
}