Advertisement

How to make a non blocking TCP socket for FTP

Started by March 27, 2004 10:23 AM
2 comments, last by mcguilejoe 20 years, 10 months ago
I am making an FTP client program using TCP IP sockets of course in C++. I have set it up so as you can connect to any ftp site in the world and then my program is supposed to recv() from the server the response message (or welcome message). I am trying to make this a non blocking call somehow. Following Johnnie's article about this, basically what I did was recv 1 character at a time checking if it's a newline (for 1 line input at a time). But this works great if there's only 1 line waiting for me, but what if there's 10 or 100 lines? How do I check the FTP server's response? Here is my code:

void Ftp::GetReply()
{
	string message;

	while ( 1 )
	{
		//////////////////////////////////////////////////

		// Get a line of input from the server

		char c;
		int bytesReceived = recv( m_clientSocket.GetSocket(), &c, 1, 0 );
		if ( bytesReceived <= 0 )
		{
			 break;
		}

		if ( c == '\n' )
		{
			// print out buffer contents

			for ( int i = 0; i < message.size(); ++i )
			{
				cout << message[ i ];
			}

			message.empty();
		} 
		else 
		{
			message += c;
		}
		
		//////////////////////////////////////////////////

	}
}	
POST: Yes, I know about threads, but I really don't want to use them. I also know about the select() function, but I'm not sure that can help me in this case because I know right after logging in or giving any FTP commands to the server, there will always be a response waiting. Please, any help is appreciated! [edited by - mcguilejoe on March 27, 2004 11:28:31 AM]
You don''t know that there''s an immediate answer. The other end may be overloaded and have high response times, or a packet may be dropped and cause a delay before re-transmission.

Using select() and building your protocol handler as a state machine is the way to go if you don''t want to use threads (or, possibly, fibers). Typically, you''d be using select(), and if there''s data, read it, and append it to a buffer. Then you check whether the buffer contains a complete command or not.

Also, you can set your socket in non-blocking mode, in winsock2 using ioctlsocket with FIONBIO. This will return whatever data is there, if any, and immediately return to you.

Note that all network protocols contain a way of figuring out whether a reply is complete or not, so you need to wait until you''ve received a complete reply before you start processing it.

State machines like these may feel a little alien; if you want to code a serial dialog (send this, then expect this, then send this ...) while still running a program message pump, and not using state machines, then you have to use threads or fibers.
enum Bool { True, False, FileNotFound };
Advertisement
I generally use select to check if I can send or recieve data, and if I can''t, I sleep a quarter of a second or so that we don''t hog the CPU waiting around doing nothing.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
select() will sleep for you, you know...
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement