Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

How to stop blocking at recv() in C++ (Not VC++.NET)

I was transferring a file from Client to Server, and even after sending the last set of bytes of file to the server, the server was still waiting at the recv() function.

A snippet of my code is here :

void getFile(SOCKET c_socket)
{
char *memblock;
int num_of_bytes,file_buf = 100000; //any user specific number of bytes
memblock = new char [file_buf];

//dest file
ofstream dest("c:\\dest\\umg.rar",ios::app | ios::binary);

while(true)
{
//reading "num_of_bytes" byte(s) from sourcefile
num_of_bytes = recv( c_socket, memblock, file_buf, 0 );

//writing "num_of_bytes" byte(s) to destination file
dest.write(memblock,num_of_bytes);

//last bunch of bytes recieved
if(num_of_bytes == 0) break;

}

//closing source and destination files.
dest.close();

printf("\n The file was successfully copied.\n");

delete memblock;
//system("pause");

return;
}

here the while loop never terminates and the control again reaches to the recv() function.
When i see the file in this case(i.e. when the control is inside the loop and the program still running) it is not copied at the server and some bytes are remaining. And when i closed the Client apllication, the remaining bytes were copied to the file at the server end.

One of my friend told me that some bytes are still in the client buffer which are copied to the file and when i close the client application, those remaining bytes from the buffer are copied to the file. To eliminate this he told me to use this condition instead :

//last bunch of bytes recieved
if(num_of_bytes < file_buf) break;

so this worked fine. But he still says that i should have flushed the socket buffer instead(both at the client end and server end ), either before sending the bytes or after receiving.

Secondly,
when my friend told me the

//last bunch of bytes recieved
if(num_of_bytes < file_buf) break;

condition, I thought that when the file with exactly the same size will come, then what will happen?

So if I don't use this way, then what can I do? How can I prevent the loop to block at recv().

He also told me that I can send any dummy value like "OK" or "DONE" etc... when all the bytes of the file have been sent from the client end, I tried this but my Server was unable to understand this dummy value, so it again blocked at recv(). I am not getting any other way, please show me some way. Will I Have to flush the buffer or use some other way to stop the server from blocking at the recv().

Please Help.
Pawan
[2712 byte] By [ppuniversal] at [2007-11-11 10:22:15]
# 1 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
theres a command to make then non blocking - is something like "ioctrl" but a search in the help on blocking should bring up the command
jonnin at 2007-11-11 20:59:00 >
# 2 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
or maybe its ioctl. I cant remember
jonnin at 2007-11-11 21:00:06 >
# 3 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
it's called select()
Danny at 2007-11-11 21:01:05 >
# 4 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
See what I want to ask is : Is there any way that the control does not comes back to my recv() function when the client has finished sending the file.Here I wanted to ask for some condition which my server should understand so that after reading the last bytes of the file, it gets out of the loop. I got a suggestion from somewhere that I can close the socket after the last bytes but I cannot do this as I have to perform more tasks between the server and client.

Please read my previous post with the code to clearly understand my problem.

Waiting for reply...
Pawan
ppuniversal at 2007-11-11 21:02:04 >
# 5 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
Look at the select() function, and in general, non-blocking I/O. select has many options and operation modes, including the closing of a socket that is no longer used. However, if you need to perform additional tasks, perhaps closing the socket isn't such a good idea?
Danny at 2007-11-11 21:03:10 >
# 6 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
Protocol is probably the answer you want. You get the remote computer to tell you the expected size and when you read enough or time out you terminate. Isnt this how most things work such as FTP ?
jonnin at 2007-11-11 21:04:09 >
# 7 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
I would suggest ensuring that the server program, which transfer the file using send function, properly close the socket at the end using shutdown and then closesocket functions. This way the receiver should obtain zero bytes from recv function.
Viorel at 2007-11-11 21:05:02 >
# 8 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
I think the protocol method i.e. sending the file size and then the file will do it for me.

Any other suggestion is welcome.

Pawan
ppuniversal at 2007-11-11 21:06:10 >
# 9 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
I think the protocol method i.e. sending the file size and then the file will do it for me.

Any other suggestion is welcome.

Pawan

Hi,

I think timeout is what you want to ask... check the bellow link at "How can I implement a timeout on a call to recv()?"

http://retran.com/beej/faq.html

Hope this help..
Ticuvina at 2007-11-11 21:07:07 >
# 10 Re: How to stop blocking at recv() in C++ (Not VC++.NET)
Hi,

You can give a 0 bytes recv if the number of bytes received do not match the requested bytes to receive. Try doing this and see if it solves the problem.

eg:

num_of_bytes = recv( c_socket, memblock, file_buf, 0 );
if (num_of_bytes == SOCKET_ERROR)
recv(c_socket, memblock, 0, 0)

Regards,
Vinoj
vinojkumar at 2007-11-11 21:08:15 >