C - Inconsistent Data from Socket : <p>I've got a simple proxy server program written in C for a course. I'm having some issues with inconsistent data. When I request the website, I save the resulting data in a file on the server side, then send it over to the client and save it on the client side as well. The results on both the client and server will be of different sizes and it appears that some of the HTML is being duplicated. Typically, the file saved on the server will be smaller than the one saved on the client, although both files are still larger than the actual web page (i.e., if I were to right click the page and 'save as', the resulting page is smaller than those returned by my code). I've tried various things to resolve this issue and nothing seems to work. The results even seem to differ between attempts at the same website. For instance, I can request the same website twice, yet the file sizes differ from both attempts. In very rare occasions, especially on small websites, both the client and server program return the correct web page and both files are of the appropriate size.</p>

<p>Note: I'm aware that the code is still rather messy. I'm more worried about addressing this issue before I move any further. I will address issues (such as checking if the socket failed to open) once this issue is corrected, so please only address the issue I have outlined.</p>

<p>Server.c</p>

<pre><code>#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netdb.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;regex.h&gt;
#include &lt;time.h&gt;

/*Code used to resolve URL into IP address adapted from following URL:
http://www.binarytides.com/hostname-to-ip-address-c-sockets-linux/
*/

//This code has been adapted from the server code provided in class

int main(int argc, char** argv)
{
    char str[655360];
    char recvline[655360];
    char parsedRecv[655360];
    char domain[1025];
    char directory[1025];
    char absoluteURL[1025];
    char temp[1025];


    int listen_fd, conn_fd, n, tempCount;
    struct sockaddr_in servaddr;
    int bytesRead;
    int stringCounter;

    int port;

    FILE *fp;

    //Variables used for second socket and resolving of host
    char ip[100];
    int sockfd, secondSocketCount;
    int len = sizeof(struct sockaddr);
    struct sockaddr_in secondServaddr;
    struct addrinfo *servinfo, *p;
    struct sockaddr_in *h;
    int rv;
    char simpleMatch[10];
    int flag = 0;
    //End

    //Used for HTTP GET request
    char request[2049];

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&amp;servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htons(INADDR_ANY);
    if(argc &lt; 2)
    {
        printf("Error! Enter a port number to run this server on.\n\tEx: ./server 22000\n\r\0");
        return 0;
    }
    else
    {
        port = atoi(argv[1]);
    }

    servaddr.sin_port = htons(port);

    printf("\n");
    printf("Awaiting connections...\n");

    bind(listen_fd, (struct sockaddr*)&amp;servaddr, sizeof(servaddr));
    listen(listen_fd, 10);

    //Once the server is listening, enter an infinite loop to keep listening
    while(1)
    {
        conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
        bytesRead = read(conn_fd, recvline, sizeof(recvline));
        if(bytesRead &gt; 0) //data read
        {
            recvline[bytesRead] = '\0';

            bzero(absoluteURL, 1025);
            strcpy(absoluteURL, recvline);

            //Extract host and page from recvline
            //For loop used to check if URL begins with HTTP or HTTPS
            for(stringCounter = 0; stringCounter &lt; 5; stringCounter++)
            {
                simpleMatch[stringCounter] = tolower(recvline[stringCounter]);
            }
            simpleMatch[strlen(simpleMatch)] = '\0';
            if(strcmp("http:", simpleMatch) == 0)
            {
                for(stringCounter = 7, tempCount = 0; stringCounter &lt; strlen(recvline); stringCounter++, tempCount++)
                {
                    temp[tempCount] = recvline[stringCounter];
                }
                temp[strlen(temp)] = '\0';
                strcpy(recvline, temp);
            }
            else if(strcmp("https", simpleMatch) == 0)
            {
                for(stringCounter = 8, tempCount = 0; stringCounter &lt; strlen(recvline); stringCounter++, tempCount++)
                {
                    temp[tempCount] = recvline[stringCounter];
                }
                temp[strlen(temp)] = '\0';
                strcpy(recvline, temp);
            }

            //printf("\n\nAfter stripping HTTP, we are left with: %s\n\n", recvline);

            //Now that HTTP:// or HTTPS:// has been stripped, can parse for domain
            for(stringCounter = 0, tempCount = 0; stringCounter &lt; strlen(recvline); stringCounter++)
            {
                //moving domain into the domain string
                if(flag == 0)
                {
                    if(recvline[stringCounter] != '/')
                    {
                        domain[stringCounter] = recvline[stringCounter];
                    }
                    else
                    {
                        domain[stringCounter + 1] = '\0';
                        //directory[tempCount] = recvline[stringCounter];
                        flag = 1;
                        tempCount++;
                    }
                }
                else
                {
                    directory[tempCount] = recvline[stringCounter];
                    tempCount++;
                }
            }

            //printf("\n\nDirectory is: %s\n\n", directory);

            //reset flag and append '\0' to directory and domain
            flag = 0;
            if(tempCount &lt; 1025)
            {
                directory[tempCount] = '\0';
            }
            //directory[strlen(directory)] = '\0';
            //domain[strlen(domain)] = '\0';

            //Done extracting

            //Resolve hostname to IP

            if((rv = getaddrinfo(domain, NULL, NULL, &amp;servinfo)) != 0)
            {
                printf("Error: an IP address cannot be resolved for %s\n", domain);
                return 0;
                //fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            }
            else
            {
                for(p = servinfo; p != NULL; p = p-&gt;ai_next)
                {
                    h = (struct sockaddr_in *) p-&gt;ai_addr;
                    strcpy(ip, inet_ntoa(h-&gt;sin_addr));
                }

                freeaddrinfo (servinfo);

                printf("%s resolved to: %s\n", domain, ip);
            }
            //End Resolve

            //Now that the IP is resolved, open a socket and connect to the IP

            //Open socket
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            bzero(&amp;secondServaddr, sizeof(secondServaddr));

            secondServaddr.sin_family = AF_INET;
            secondServaddr.sin_port = htons(80);

            inet_pton(AF_INET, ip, &amp;(secondServaddr.sin_addr)); //IP taken from earlier resolution
            connect(sockfd, (struct sockaddr*) &amp;secondServaddr, sizeof(secondServaddr));

            //socket is open, can create and send request, finally
            bzero(request, 2049);
            //sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", directory, domain);
            //sprintf(request, "GET %s HTTP/1.1\r\n\r\n", absoluteURL);
            //sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", absoluteURL, domain);
            sprintf(request, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", directory, domain);

            write(sockfd, request, strlen(request));

            printf("\tAttempting to retrieve data: this may be slow.\n");

            bzero(recvline, 655360);
            bzero(parsedRecv, 655360);

            //Old method used to retrieve data
            //This was changed when I began to run into issues
            /*while(1)
            {
                secondSocketCount = read(sockfd, parsedRecv, sizeof(parsedRecv));
                if(secondSocketCount == -1)
                {
                    printf("Error receiving data: server terminating.\n");
                    return 0;
                }
                else if(secondSocketCount == 0)
                {
                    //no more data
                    break;
                }
                strcat(recvline, parsedRecv);
            }*/

            //This while loop is used to read in data (the response from the server)
            bzero(str, 655360);
            while(secondSocketCount = read(sockfd, recvline, sizeof(recvline)) &gt; 0)
            {
                strcat(str, recvline);
            }
            //bzero(parsedRecv, 655360);
            //recvline[strlen(recvline)] = '\0';

            printf("\tData retrieved from main server.\n");

            //This for loop finds the end of the HTTP header and copies everything after into parsedRecv
            for(stringCounter = 0, tempCount = 0; stringCounter &lt; strlen(str); stringCounter++)
                {
                    //lazy if statement to find two \r\n in a row to mark the end of the header
                    if(str[stringCounter] == '\r' &amp;&amp; str[stringCounter + 1] == '\n' &amp;&amp; str[stringCounter + 2] == '\r' &amp;&amp; str[stringCounter + 3] == '\n' &amp;&amp; flag == 0)
                    {
                        flag = 1;
                        stringCounter += 3;
                    }
                    if(flag == 1)
                    {
                        parsedRecv[tempCount] = str[stringCounter];
                        tempCount++;
                    }
                }
            flag = 0;
            parsedRecv[strlen(parsedRecv)] = '\0';
            fp = fopen("ReturnedPageServer.html", "w");
            if(fp != NULL)
            {
                fprintf(fp, "%s", parsedRecv);
                //fprintf(fp, "%s", recvline);
            }
            fclose(fp);
            printf("\tData saved to ReturnedPageServer.html\n");

        }

        //strcpy(str, "This is a test of the Hello World Broadcast System.\n");
        bzero(str, 655360);
        strcpy(str, parsedRecv);
        write(conn_fd, str, strlen(str));
        close(conn_fd);
        printf("\tData sent to client.\n");
        printf("Awaiting further connections...\n");

        //strcpy(directory, "");
        //strcpy(domain, "");
        //strcpy(recvline, "");
        bzero(directory, 1025);
        bzero(domain, 1025);
        bzero(temp, 1025);
        bzero(recvline, 655360);
    }
    return 0;
}
</code></pre>

<p>Client.c</p>

<pre><code>#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netdb.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

//Code adapted from client code provided in class

int main(int argc, char** argv)
{
    int sockfd, n, port;
    int len = sizeof(struct sockaddr);
    char sendline[10000];
    char recvline[655360];
    struct sockaddr_in servaddr;

    FILE *fp;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    bzero(&amp;servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    if(argc &lt; 2)
    {
        printf("Error! Enter the port number for the server.\n\tEx: ./client 22000\n\r\0");
        return 0;
    }
    else
    {
        port = atoi(argv[1]);
    }
    servaddr.sin_port = htons(port);

    inet_pton(AF_INET, "129.120.151.94", &amp;(servaddr.sin_addr)); //CSE01 IP
    connect(sockfd, (struct sockaddr*) &amp;servaddr, sizeof(servaddr));

    printf("url: ");
    scanf("%s", sendline);

    //strcpy(sendline, "The server should display this text.\n\0");
    //printf("\nLength of string: %d\n", strlen(sendline));
    //printf("\t%s\n", sendline);
    write(sockfd, sendline, strlen(sendline));

    fp = fopen("ReturnedPageClient.html", "w");
    bzero(recvline, 655360);
    while(n = read(sockfd, recvline, sizeof(recvline)) &gt; 0)
    {
        //printf("%s", recvline);
        if(fp != NULL)
        {
            fprintf(fp, "%s", recvline);
        }
        else
        {
            printf("\tError saving file: client terminating.\n");
            fclose(fp);
            return 0;
        }

    }
    fclose(fp);
    printf("\tResponse received from proxy server.\n\tFile saved as \"ReturnedPageClient.html\"\n");
    close(sockfd);
    return 0;
}
</code></pre>
