I have client server architecture wherein I transfer a binary file from server to client.
Server Code:
FILE *outFile = fopen("/tmp/localpkg.deb","wb");
if( outFile == NULL )
{
RPTLOG(1, "Error opening file for writing.\n");
return -1;
}
FILE *readFilefp = fopen(file_name, "rb");
if ( readFilefp == NULL)
{
RPTLOG(1, "Error opening file.\n");
return -1;
}
char fileBuffer[1024];
bzero(fileBuffer, 1024);
while(1)
{
size_t readSize = fread(fileBuffer, sizeof(char), sizeof(fileBuffer) -1, readFilefp);
if(readSize == 0)
{
RPTLOG(1, "No more contents are left in file.\n");
n = write(sockfd, "\r\n", 2);
break;
}
n = write(sockfd, fileBuffer,readSize);
fwrite(&fileBuffer, sizeof(char), readSize, outFile);
RPTLOG(1, "Data[%d] written to sock=%s.\n", n, fileBuffer);
bzero(fileBuffer, 1024);
}
fclose(readFilefp);
fclose(outFile);
char *endfile_var =(char*) malloc(2048);
bzero(endfile_var,100);
strcpy(endfile_var,"ENDFILE\r\n");
n = write(sockfd, endfile_var, 9 );
RPTLOG(1, "ENDFILE text sent to client[%s] NumBytes sent=%d\n", endfile_var, n );
Client code:
FILE *fp = fopen(localfile, "wb");
if( fp == NULL )
{
RPTLOG(1, "Not enough permissions to write on disk, exiting....\n");
break;
}
memset(buf, 0, 2048);
//Started receiving installation package from server
while ((ret = read(sock, buf, 2047)) > 0) //Stcuk point: read blocks over here when it is about to receive last few lines of
{ //binary file from server
buf[ret] = '\0';
if ( ret == 1 )
{
RPTLOG(1, "Caught character where ret = %d\n", ret);
if ( buf[0] == '\n' )
continue;
}
if (strstr(buf, "ENDFILE") != 0 )
{
RPTLOG(1, "Endfile detected\n");
break;
}
else
{
fwrite(buf, 1, ret, fp);
}
memset(buf, 0, 2048);
}
if( ret == 0)
{
RPTLOG(4, "Connection closed from server = %d \n", ret );
}
else if( ret < 0)
{
RPTLOG(4, "Read error on client socket= %d \n", ret );
}
fclose(fp);
My Problem: When server is about to send last few lines of binary file, client stuck in read call [stuck point in client code posted above]. Here client program is designed in such a way that when it receives "ENDFILE" line from server it will assume that file contents have been ended from server side and come out of while loop.
So kindly suggest the solution to receive binary file from server successfully.
[Special Note:] Client code has been wrapped up in a build and installed at customer end. So I have to make changes in server side code only. Also as indicated in server code above, for debugging purpose I have written content sent on socket to '/tmp/localpkg.deb' file as well. And that file contains all the contents which were written on socket at server side.
[Special Note 2:] When I try to send plain text file, I can send it successfully. Problem comes in only while sending binary file. Thanks in advance.
The reason why your code fails is simple enough. You are reading a chunk of binary data into your buf, and than you call strstr
on this buf. strstr
goes until first \0
byte when looking for given token. Obviously, binary data will have a lot of those, so search stops after first one encountered and returns 'nothing was found'.
As a result, your code never exits the read loop, and keeps waiting for more data to arrive from the server - which will never send it.
The proper solution is, of course, implement a proper protocol for sending binary data. However, if this is impossible due to the listed constraints, a semi-workable solution would be to to replace strstr
function with a custom one, which will go over provided buffer ignoring the the nul-terminators (using size of the buffer instead) and looks for the token provided. It will still break if your binary data has the token in it, but there is nothing you can do about it.