OVB
OVB

Reputation: 227

Client reads lesser bytes than Server is sending on sockets

My server code is as follows:

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;
}

And my client code is as follows:

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;
        }
    }

The server is saying it has sent all 43000 bytes, but client says it has received only 32768 bytes.

Appreciate any help! Thanks

Upvotes: 1

Views: 124

Answers (3)

Viswesn
Viswesn

Reputation: 4880

The best way of writing client-server socket programming is to have a header before your data. The header should state the amount of data that it is going to transfer.

For example, To send data "Hello World", then send it as "0011+HELLO WORLD"

Here 11 stands for the size of the data the sender is planning to send now. The receiver on reading the first 4 bytes can understand that he should be ready to read next 11 bytes of data from the sender.

So reader will do two read: hRead = 5 /* With 5 you are saying it can read upto max of 9999 bytes from data". read(sd, buff, hRead); dRead = atoi(buff); readn(sd, buff, dRead);

For Example : Server

 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);
  }

To send message:

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

Client:

 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);
}

Upvotes: 0

LtWorf
LtWorf

Reputation: 7600

You have a bug in the sending part, you should update newLength, because if you have 1 byte left to send from the file, it will send more, going out of the memory area where the content you want to send is stored. You should fix in this way:

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

In this way the last send will have the correct size.

Also, use write instead of send if you are not using any flags.

Upvotes: 2

tjltjl
tjltjl

Reputation: 1479

You need to have the similar loop as you have on the writing side (bytes_written < filesize) on the reading side (i.e., while you can read more bytes, you should read them and append them).

The network doesn't guarantee that one read() call will return all available data.

Upvotes: 0

Related Questions