martes, 9 de junio de 2015

35 - Tutorial de C++ en español - winsock (Conectar a un server FTP)




En este capítulo del Tutorial de C++ utilizaremos la librería winsock2.h para ver un ejemplo de conexiones TCP a un servidor local o remoto, concretamente el ejemplo se realizará en un servidor local FTP (File Transfer Control), el servidor FTP Filezilla es ideal para realizar la prueba y lo puedes descargar aquí

El objetivo es enviar las credenciales de usuario al servidor para conectar y poder enviar comandos FTP a través de la consola.

Los detalles para que el programa funciones correctamente se pueden ver en el vídeo, ya que en dev-C++ es necesario crear un link en el proyecto a la librería libws2_32.a que se encuentra en la carpeta lib de dev-C++ de lo contrario obtendréis un error.

cliente-ftp.cpp


#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <winsock2.h>

using namespace std;

void client_ftp()
{
 char * host = "localhost";
 int port = 21;
 /* Estructura de datos con información del winsock */
 WSADATA wsa; 
 /* Estructura de datos para especificar un servidor local o remoto para conectar un socket */
 SOCKADDR_IN server;
 /* Objeto que permite establecer conexiones locales o remotas e intercambiar datos */
 SOCKET sock;
 
 /* Inicializar winsock, comprobar versión 2.2 */
 
 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
 {
  cout << "Error: " << WSAGetLastError() << endl;                       
 }
 else
 {
     
 cout << "Inicializando ... " << endl;
 
 /* Crear un socket */
 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
 {
  cout << "No se pudo crear el socket: " << WSAGetLastError() << endl;       
 }
 else /* Se ha creado el socket */
 {
     
 cout << "Socket creado correctamente ... " << endl;
 
 /* Configurar la conexión al servidor */
 server.sin_family = PF_INET;
 server.sin_port = htons(port);
 server.sin_addr = *((struct in_addr *)gethostbyname(host)->h_addr);
 memset(server.sin_zero, 0, 8);
 
 /* Conectar al servidor */
 connect(sock, (LPSOCKADDR)&server, sizeof(struct sockaddr));
 Sleep(1000);
 
 /* Respuesta del servidor */
 char serverMsg[2048];
 cout << "Esperando una respuesta del servidor ... " << endl;
 recv(sock, serverMsg, 2048, 0);
 serverMsg[0] = '\0';
 cout << "Respuesta del servidor: " << serverMsg << endl;
 
 //Enviar credenciales USER y PASS
 char * user = "USER manu\r\n";
 int user_send = send(sock, user, strlen(user), 0);
 cout << "Enviado: " << user << user_send << " bytes" << endl;
 Sleep(1000);
 
 //Esperar respuesta del servidor para enviar el password
 cout << "Esperando una respuesta del servidor ..." << endl;
 serverMsg[0] = '\0';
 recv(sock, serverMsg, 2048, 0);
 cout << "Respuesta del servidor: " << serverMsg << endl;
 
 //Enviar el password
 char * pass = "PASS password\r\n";
 int pass_send = send(sock, pass, strlen(pass), 0);
 cout << "Enviado: " << pass << pass_send << " bytes" << endl;
 Sleep(1000);
 
 //Esperar a la respuesta del servidor para enviar comandos
 cout << "Esperando una respuesta del servidor ..." << endl;
 serverMsg[0] = '\0';
 recv(sock, serverMsg, 2048, 0);
 cout << "Respuesta del servidor: " << serverMsg << endl;
 
 //Enviar comandos
 cout << "Comando: ";
 string comando;
 getline(cin, comando);
 comando = comando + "\r\n";
 int comando_send = send(sock, comando.c_str(), strlen(comando.c_str()), 0);
 cout << "Enviado: " << comando << comando_send << " bytes" << endl;
 Sleep(1000);
 
 //Esperar una respuesta del servidor
 cout << "Esperando una respuesta del servidor ... " << endl;
 serverMsg[0] = '\0';
 recv(sock, serverMsg, 2048, 0);
 cout << "Respuesta del servidor: " << serverMsg << endl;
 system("PAUSE");
 
 //Cerrar la conexión
 closesocket(sock);
 WSACleanup();
 
 //Llamar nuevamente a la función
 client_ftp();
 }
 }
}

int main(int argc, char *argv[])
{
    client_ftp();
    system("PAUSE");
    return EXIT_SUCCESS;
}