Reputation: 13
I am trying to create FTP client in C++ using BSD sockets, I can create socket, get welcome message, send user name, but I can not move on. Here is my dubug output:
Socket created
Connected
220 server - welcome message
Msg: USER anonymous
Received bytes: 75
331 Anonymous login ok, send your complete email address as your password
Then I am stucked at this point for 5 minutes, server terminates connection and I finally get response:
Received bytes: 61
331 Anonymous login ok, send your complete email address as your password
421 Login timeout (300 seconds): closing control connection
our password
Received bytes: 0
Msg: PASS password
Received bytes: 0
Msg: SYST
Received bytes: 0
Msg: PASV
Received bytes: 0
Msg: LIST
Received bytes: 0
Msg: QUIT
Received bytes: 0
Program ended with exit code: 0
Here is my function for sending and receiving messages. I put there socket and message for FTP server (for example USER anonymous\r\n
)
void communication(int sock, const char *msg) {
string response;
char server_reply[2000];
printf("Msg: %s\n", msg);
send(sock, msg, strlen(msg), 0);
//Receive a reply from the server
int rval;
do
{
rval = (int) recv(sock , server_reply , 2000 , 0);
printf("Received bytes: %d\n", rval);
if (rval <= 0)
{
break;
}
else {
response.append(server_reply);
puts(response.c_str());
}
}
while (true);
My program looks like this:
//Receive a welcome message from the server
if( recv(sock , server_reply , 2000 , 0) < 0) {
puts("recv failed");
}
puts(server_reply);
memset(&server_reply[0], 0, sizeof(server_reply));
const char *usernameMsg = "USER anonymous\r\n";`
communication(sock, usernameMsg);`
const char *passwdMsg = "PASS [email protected]\r\n";`
communication(sock, passwdMsg);
communication(sock, "SYST\r\n");
communication(sock, "PASV\r\n");
communication(sock, "LIST\r\n");
communication(sock, "QUIT\r\n");
Could you tell me, what's wrong please? Thank you
Upvotes: 0
Views: 1128
Reputation: 202474
You obviously expect the recv
to return 0, when there's no more response from the server.
But that's wrong for blocking mode. In the blocking mode recv
will always wait until there are some data. Note that the socket is a generic interface to a connection. The connection is a just a stream of data. There's no end-of-the-message mark. So the socket cannot magically find out that a complete response was received from the FTP server. It's up to you. It's you task to call recv
only until you receive the CRLF sequence, which signals the end-of-the-response in the FTP protocol. And it's actually even more complicated as the FTP response can be multi-line. Read the FTP specification.
Your primary problem now, is that your first call to the communication()
function never finishes.
Once you read the 331
response to the USER
command, you start waiting for the next message (second round [or even later, in the rare case the 331
response is longer than the 2000 characters] of the while
loop in the first call of the communication()
function). But the server is actually waiting for your next command, which you never send. So the server eventually gives up, sends you the 421
response and disconnects you.
Upvotes: 1