Click here to Skip to main content
15,886,518 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I working on a project about downloading file from one client to another. I read file in source client with 1000 bytes or smaller char* arrays and then write these received arrays to file with socket programming. everything is OK but the result file is not as same as the source file and some characters is changing.
here is the code in source client:

C++
ifstream infile(file,ios::binary);
unsigned int filesize = Getfilesize(file.c_str()); // GetfileSize returns file size
while(!infile.eof()){
        char chunk[1000];
        int sizeofbuf = 0;
	if(filesize<1000)
	{
		sizeofbuf = filesize;
		filesize = 0;
	}
	else
	{
		sizeofbuf = 1000;
		filesize = filesize - 1000;
	}
	if(sizeofbuf==0)
		break;
	infile.read(chunk,sizeofbuf);
	send(ParentSocket,chunk,sizeofbuf,0);
	ZeroMemory(chunk,1000);
}
infile.close();


and the code in distination is:


C++
//i have received file size before with socket programming
FILE* fout = fopen(newname,"a+");
while(1){
	
	ZeroMemory(Message,1000);
	int sizeofbuf=0;
	if(filesize<1000)
	{
		sizeofbuf = filesize;
		filesize = 0;
	}
	else
	{
		sizeofbuf = 1000;
		filesize = filesize - 1000;
	}
	if(sizeofbuf == 0)
		break;
			
	bytesRecv = recv( ClientSocket, Message, sizeofbuf, 0 );
	if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
	{
		cout<<"\nConnection Closed.\n";
		
		
		return NULL;
	}
	fwrite(Message,1,sizeofbuf,fout);
	fclose(fout);
	bytesRecv = 0;
	if(sizeofbuf<1000)
		break;
}
		
fclose(fout);


thank you programmer society.
Posted
Updated 8-Nov-13 23:34pm
v2
Comments
Sergey Alexandrovich Kryukov 9-Nov-13 5:40am    
What is the difference between input and output data? Will your code work correctly if the file size is exactly N*1000?
—SA
Mohibur Rashid 9-Nov-13 6:46am    
You are creating your receiver file with a+ which is text mode, to write the binary you will have to open it with b in your string

1 solution

1. Create the file in binary mode as Mohibur Rashid suggested.

2. When callin fwrite write out bytesRecv number of bytes instead of sizeofbuf bytes.

3. Check the value of bytesRecv before writing the file and if its zero then the peer has shut down its send channel signaling to you basically an EOF (Note that close usually shuts down both the send and recv channels on popular OSes, many people are unaware between the difference of closing and shutting down. When a peer shuts down just its send channel you may still be able to send data to that peer if its recv channel isnt shut down. You usually get WSAECONNRESET if you try to send data to a peer that shut down its recv channel.). You don't have to handle any specific errors like WSAECONNRESET (that has nothing to do with a zero return value that is a completely different thing). Instead of handling WSAECONNRESET or any other specific error code check if bytesRecv is negative. Basically you should check only 3 cases: negative bytesRecv -> error, zero bytesRecv -> peer_shutdown_its_client_channel(eof, peer signals that it doesnt want to send more data), bytesRecv>0 -> you received bytesRecv number of bytes.

4. bytesRecv and WSAECONNRESET have nothing to do with each other, if their value are the same then its just a coincidence. When bytesRecv is negative you can print out diagnostic info for yourself if you want by querying errno on unix or WSAGetLastError() on windows, you get WSAECONNRESET and its friends here and not from bytesRecv that is negative in case of error.

5. in case of send() you are not really sending, you are just memcpy-ing data into the OS owned buffer associated with that socket. by default that buffer is only a few kilobytes. If that buffer doesnt have enough space to hold the data you want to send then only a few bytes will be copied from your buffer to the send buffer of the socket handle. In that case send() returns less than the number of bytes you wanted to write and you have to handle this. You should handle the return value of send(): zero or negative value: error, positive value: this return value indicates the number of bytes actually sent.

C++
ifstream infile(file,ios::binary);
unsigned int filesize = Getfilesize(file.c_str()); // GetfileSize returns file size
while(!infile.eof()){
        char chunk[1000];
        int sizeofbuf = 0;
	if(filesize<1000)
	{
		sizeofbuf = filesize;
		filesize = 0;
	}
	else
	{
		sizeofbuf = 1000;
		filesize = filesize - 1000;
	}
	if(sizeofbuf==0)
		break;

	// BUG
	infile.read(chunk,sizeofbuf);

	// BUG: unhandled return value, will always work with few kilobyte files
	// that are smaller than the default send buf size of the socket, will randomly fail otherwise
	send(ParentSocket,chunk,sizeofbuf,0);

	// WHY????
	ZeroMemory(chunk,1000);
}
infile.close();


C++

// BUG: use binary mode
FILE* fout = fopen(newname,"a+");
while(1){
	// WHY???
	ZeroMemory(Message,1000);
	int sizeofbuf=0;

	// BUG: What is this filesize related copy-paste bloat here???
	if(filesize<1000)
	{
		sizeofbuf = filesize;
		filesize = 0;
	}
	else
	{
		sizeofbuf = 1000;
		filesize = filesize - 1000;
	}
	if(sizeofbuf == 0)
		break;


	// BUG: instead of sizeofbuf use sizeof(Message)
	bytesRecv = recv( ClientSocket, Message, sizeofbuf, 0 );

	// BUG: unhandled negative return value and bytesRecv has nothing to do with error codes
	if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )

	{
		cout<<"\nConnection Closed.\n";
		
		
		return NULL;
	}

	// BUG: sizeofbuf instead of bytesRecv
	fwrite(Message,1,sizeofbuf,fout);

	// BUG: close the output only when you break the loop. i.e. in case of zero or negative return value
	fclose(fout);

	// Whats this??? You have to break the loop only in case of zero or negative bytesRecv.
	bytesRecv = 0;
	if(sizeofbuf<1000)
		break;
}
		
fclose(fout);

So an answer to the question, why doesn't this work: because this function is a big stack of bugs copy pasted from somewhere and modified afterwards.
 
Share this answer
 
v2
Comments
xLordProgrammer 10-Nov-13 2:34am    
thanks for responses and specially thanks pasztorpisti.
I know that there are some small bugs in code, and after your response I fixed them. but the thing that is so interesting is: when I debug the program it works fine, and all received file is perfect, but when I release the program the received file is corrupted. is there any problem in sequence of packets?
pasztorpisti 10-Nov-13 8:29am    
If you fix everything I mentioned above then it will work. If it doesnt work then you havent yet fixed everything. It works fine when you debug it because when you debug the OS has enough time to empty the send buffer and to fill the recv buffer of the socket handles, when you don't debug your program is fast enough to encounter half filled buffers that you don't handle in the code.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900