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