سؤال

I have a problem that I'm hoping is a mistake as I am a bit new to linux C.

I have a server, that sends a file to a client. The code works perfectly fine over a wired connection, 100% success rate every time. However, when I try to run that same code over a 3G USB connection at -65dB (Strong), the client will usually only receive the first 1 or 2 thousand bytes of the file. (Forgive the syntax errors won't let me space properly)

        // CLIENT CODE

        char* fs_name = "/target/to/send";
        char sdbuf[LENGTH]; // Send buffer, LENGTH == 512
        printf("Sending %s to the Client... \n", fs_name);
        FILE *fs = fopen(fs_name, "r");
        if(fs == NULL)
        {
            fprintf(stderr, "ERROR: File %s not found on server. (errno = %d)\n", fs_name, errno);
            exit(1);
        }

        bzero(sdbuf, LENGTH); 
        int fs_block_sz; 
        while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs))>0)
        {
            if(send(client, sdbuf, fs_block_sz, 0) < 0)
            {
                fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", fs_name, errno);
                exit(1);
            }
            bzero(sdbuf, LENGTH);
        }
        printf("File send Success\n");



            // SERVER CODE

        char* fr_name = "/home/file/to/save";

        FILE *fr = fopen(fr_name, "a");

        if(fr == NULL)

            printf("File %s Cannot be opened.\n", fr_name);

        else
        {
                // zero out bytes
            bzero(revbuf, LENGTH); 

            int fr_block_sz = 0;

            while((fr_block_sz = recv(sd, revbuf, LENGTH, 0)) > 0)  //LENGTH == 512
            {
            int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);

                if(write_sz < fr_block_sz)
            {
                    error("File write failed.\n");
                }
            bzero(revbuf, LENGTH);
            if (fr_block_sz == 0 || fr_block_sz != 512) 
            {
            break;
            }
        }

                // error checking
        if(fr_block_sz < 0)
                {
        if (errno == EAGAIN)
        {
            printf("recv() timed out.\n");
        }
        else
        {
            fprintf(stderr, "recv() failed due to errno = %d\n", errno);
        }


            fclose(fr);

If anyone out there could shed some light on what I'm doing wrong I would be most appreciative. Thanks for reading.

EDIT: The server is Ubuntu 10.04 and the client is Arch Linux ARM and the type of file being sent is an ARM binary.

هل كانت مفيدة؟

المحلول

I think your main problem is here in your code labeled server but which really looks to be the client. You assume that the recv is going to get all 512 bytes on each recv but that's not true - you can and will get short reads. A little below you break out of the read loop if you haven't read exactly LENGTH (i.e. 512). That explains why your pgm quits after a couple of thousand bytes.

    while ((fr_block_sz = recv(sd, revbuf, LENGTH, 0)) > 0)  //LENGTH == 512
    {
        int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);

        if (write_sz < fr_block_sz)
        {
            error("File write failed.\n");
        }

        bzero(revbuf, LENGTH);

        if (fr_block_sz == 0 || fr_block_sz != 512)
        {
            break;
        }

    }

You want something more like this:

    while ((fr_block_sz = recv(sd, revbuf, LENGTH, 0)) > 0)  //LENGTH == 512
    {
        if (fr_block_sz < 0)
            if (errno == EAGAIN)
               continue;
            else
               error;

        if (fr_block_sz == 0)
            break; //done

        int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);

        if (write_sz < fr_block_sz)
        {
            error("File write failed.\n");
        }

        bzero(revbuf, LENGTH);
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top