Hi folks,
I have a very strange problem when I try to port my client/server
program to cygwin. It is a simple shell program where the server
executes client's commands + it can send and receive files (something
like ftp server/client).
I implemented all the commands which the server executes from scratch
meaning I don't use fork and exec. It was very educational but my
problem is that when I try to "get <filename>" from server to the
client in cygwin the client doesn't receive the whole file. I tracked
back and saw that the read() in the server returns end of file before
reading the whole file. I think that this might be a Windows problem
or cygwin specific problem because on my home Slackware computer the
program works perfect:
The preparation for the client to receive the file includes getting
the file size:
server: snprintf(buf, 10, "%ld", (long)dir_stat.st_size); // send the
size of the file
server: s_line(buf, sockfd); // to client
So right now I am tryting to copy a file with reported size: 34302723
bytes but read return 0 (end of file) on 34302220 bytes read. This is
a problem since the client stops waiting for data only if filesize ==
numbytes sent.
Server snip:
do
{
numbytes = read(dsc, buf, sizeof(buf));
if(numbytes == -1) {
printf("Error reading source file\n");
break;
}
else if(numbytes 0)
{
if ( (counter = write(sockfd, buf, numbytes)) < 0)
perror("get:write to socket");
total += counter;
}
else if (numbytes == 0)
printf("so far we've got %ld", total);
} while (numbytes != 0);
}
}
printf("Bytes Sent: %ld out of %ld\nFile sent successful\n",
total, (long)dir_stat.st_size);
So the last printf line on the server itself shows that there is
difference between the filesize of the file and the actual bytes sent
to clien:
Filesize: 34302723
Clients Received: 34302220
But still the while loop breaks because read returned 0 and therefore
the numbytes == 0 which is EOF if I am not mistaken.
client snip:
numbytes = read(sockfd, buf, sizeof(buf));
download += numbytes;
kbs += numbytes; // kb/s
gettimeofday(&tp2,NULL);
time +=(tp2.tv_sec - tp1.tv_sec) + (float)(tp2.tv_usec -
tp1.tv_usec)/1e6;
if (time>800) { // probably this is a second by my understandings
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b
\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b ");
printf("%.2f[KB/S]\t%.4f/%.4f[MB] \t%.1f/100%%",(double)kbs /
1024, (double)download / (1024 * 1024), (double)kbytes / (1024 *
1024), (double)download * 100 / kbytes);
fflush(stdout);
kbs = 0;
time = 0;
gettimeofday(&tp1, NULL);
}
if (numbytes == -1)
perror("get:read");
else if (download == kbytes) // we match the downloaded chunk with
the filesize
{
if (numbytes 0 && strncmp(buf, "EOF\r\n", 5)) // if there is
more data
write(file, buf, numbytes); // write last bytes before closing the
file
printf("\n%.2f[KB/S]\t%.4f/%.4f[MB] \t%.2f/100%%\n",
(double)kbs / 1024, (double)download / (1024 * 1024), (double)kbytes /
(1024 * 1024), (double)download * 100 / kbytes);
printf("\nDownloading Successful!\n");
close(file);
break;
}
else
write(file, buf, numbytes);
The client receives the file size with the string that server sends
and performs kbytes = atol(buf)
So I see that I am missing the last part of the file I transfer not
because of the socket error
but probably because the server:
1. Doesn't report the file size right
2. Doesn't read correctly until EOF is reached
By the way i am dealing with binary files so I use open().
If the server doesn't report the file size right this means that the
client must receive the whole
file but if I transfer a rar archive and I try to open it it says -
unexpected end of file found so I
guess that there is a problem which I can't figure out.
I don't know why this problem does not exist on my slackware machine!?
And one last thing - the # of bytes the server reports as read are the
number of bytes that
the client actually received - so I don't know why the server read()
doesn't proceed to the end
of the file?
Any help will be appreciated.