简体   繁体   中英

Missing Data in TCP Transmission Using Sockets In C

I am downloading an online .dat file in 200 char chunks and am some of the data is missing. Most, but not all chunks download completely but some only partly download, and there are missing characters when I print the recieved data directly to a local text file.

Thank you.

The Program I am using is below.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netdb.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <malloc.h>

#define NOT_EOF  1
#define REACHED_EOF 0
#define BUFFER_SIZE 200

struct sockaddr_storage their_addr;
socklen_t addr_size;
char inputData[200];
int newsocket;
struct timeval timeout;
char sendStr[100]; 
char method[] = "GET";

char *buffer= (char *)malloc(2*BUFFER_SIZE*sizeof(char));

FILE *testdata=fopen("testRecv.txt","w");

struct addrinfo hints, *result;
memset (&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if(getaddrinfo("www.blahblah.com","80"
                  , &hints, &result)!=0)
{
     freeaddrinfo(result);
     puts("Unable to resolve hostname.");
     exit(1);
 }

 newsocket = socket( result->ai_family, result->ai_socktype, 0);
 if(newsocket == FAILURE)
 {
    puts("Unable to create socket.");
    freeaddrinfo(result);
    close(newsocket);
    exit(1);
  }

 memset(&timeout, 0, sizeof(timeout));
 timeout.tv_sec= 10;
 timeout.tv_usec= 0;
 setsockopt(newsocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
 setsockopt(newsocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

if(connect(newsocket, result->ai_addr, result->ai_addrlen) == -1)
  {
    puts("Could not connect.");
    freeaddrinfo(result);
    close(newsocket);
   exit(1);
  }

strcpy(sendStr,method);
strcat(sendStr," /");
strcat(sendStr,subdomain);
strcat(sendStr," HTTP/1.0\r\nHost: ");
strcat(sendStr,hostname);
strcat(sendStr,"\r\n\r\n");

if( send(newsocket,sendStr,strlen(sendStr),0) == FAILURE)
 printf("Unable to send message\n");

 while(not_eof=NOT_EOF)
   {
       bytes_recieved=recv(newsocket,buffer,BUFFER_SIZE,0);

       fprintf(testdata,"%s",buffer);

       if(bytes_recieved == 0 || *(buffer+bytes_recieved) == EOF)
       not_eof=REACHED_EOF;
    }

You can't call recv just once. Since you're in blocking mode, you must call it in a loop and check whether its return value is positive. If it's negative, there's been an error, if it's zero, the socket has been orderly shutdown.

The recv call is not guaranteed to receive all of the data in a single call. With a 200 byte data size, one would expect the entire data in one call, but it may not always be the case. If it was not all received in one call, you would need to call recv again.

Edit The changes as shown (if it is the real code) still seems like it needs work. The fprintf call is made regardless of the return value. Thus, the loop executed twice and the second recv call failed, the buffer would be written twice. Also, I don't think that buffer is guaranteed to be null terminated, so the fprintf(...%s...) call may have unpredictable results. It seems, though, the primary issue is that the possibility of a return value of -1 (error case) is not handled. In theory, that would result in it loop infinitely. Actually, it would loop infinitely as currently shown regardless since the while loop has a single equals and would assign 1 to the flag each iteration (but I assume that is a typo in the edit).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM