miércoles, 2 de julio de 2014

Servidor de Echo en C++ para Linux.

Buenas gente. Ésta es la última práctica que se pidió para redes. Montar un servidor de Echo en C++ para Ubuntu. Me ha sido super trabajoso conseguirlo porque a mi ordenador le ha costado vida y media tirar de la máquina virtual (para compilar) y del Visual Studio para programar. Bueno, el servidor debe seguir el siguiente esquema:

Como veis parece ser seguir una estructura, pero el averiguar de donde sacar los datos nos costó (tanto a Cristina como a mi) demasiado tiempo. Seguramente haya códigos mejores que el mio, pues no soy perfecto. Pero espero que os sirva de ayuda. Aquí los teneis:

Código del Cliente:
#include <iostream>
#include <sys/socket.h>    //socket
#include<stdio.h> //printf
#include<netinet/in.h> 
#include<arpa/inet.h>  //inet_addr
#include<netdb.h>
#include<string.h>    //strlen
#include <stdlib.h>  // para atoi


using namespace std;





int main(int argc, char *argv[]) {
 int sck, rtn;
// const int PUERTO = 5050;
 const int PUERTO = atoi(argv[argc-1]);
 cout << argv[1] << ":" << PUERTO << "\n\n";

 struct sockaddr_in server;
 char bufferIn[2000], bufferOut[2000], bufferAux[2000];
 //creamos socket
 sck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 if (sck == -1) {
  cout << "No se puede crear el socket";
 }
 puts("Socket creado");

 server.sin_family = PF_INET;
 server.sin_port = htons(PUERTO);
 server.sin_addr.s_addr = inet_addr(argv[1]);
// server.sin_addr.s_addr = inet_addr("127.0.0.1");

 //Conectando al servidor
 if (connect(sck, (struct sockaddr*) (&server), sizeof(server)) < 0) {
  perror("Conexion fallida. error");
  return 1;
 }
 puts("Conectado\n");
 
 //Obtenemos la string a enviar, la separamos en caracteres y la enviamos.
 bool noAcaba = true;
 while (noAcaba) {
  cout << "Conectado al servidor " << inet_ntoa(server.sin_addr) << ":" << PUERTO << ".\n";
  cout << "Que desea enviar?\n";
  scanf("%s", bufferOut);
  if (!strcmp(bufferOut, "FIN")) {
   noAcaba = false; 
   if (write(sck, bufferOut, strlen(bufferOut)) < 0) {
    puts("envio fallido");
    return 1;
   }
  } else {
   strcat(bufferOut, "\n");

   if (write(sck, bufferOut, strlen(bufferOut)) < 0) {
    puts("envio fallido");
    return 1;
   }
   rtn = read(sck, bufferIn, 2000);
   
   cout << "\nDevuelto " ; 
   for (int i = 0; i < strlen(bufferOut); i++) {
    cout << bufferIn[i];
   }
   cout << "\n";
   strcpy(bufferIn, "\0");
   strcpy(bufferOut, "\0");
  }
  

 }
 cout << "Desconectado Correctamente.\n";
 

 return 0;
}

Código del Servidor:
// EchoServer.cpp: define el punto de entrada de la aplicación de consola.
//

#include <iostream>
#include <sys/socket.h> 
#include <unistd.h>  //write
#include <stdio.h>  //para perror
#include <stdlib.h>  // para atoi

//Otros includes:
#include<netinet/in.h> 
#include<arpa/inet.h> //inet_addr
#include<netdb.h>
#include<string.h>  //strlen

using namespace std;




int main(int argc, char *argv[]) {

 int listen_socket, cliente, rtn;
 struct sockaddr_in server, clientinfo;
// const int PUERTO = 5050;
 const int PUERTO = atoi(argv[1]);

 //SOCKET
 listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
 if (listen_socket == -1) {
  perror("No se puede crear el socket");
  return 1;
 }
 cout << "Socket creado\n";

 //preparar la estructura sockaddr_in
 server.sin_family = AF_INET;
 server.sin_addr.s_addr = INADDR_ANY;
 server.sin_port = htons(PUERTO);
 
 //BIND
 rtn = bind(listen_socket, (struct sockaddr*)&server, sizeof(server));
 if (rtn < 0) {
  perror("Error en el bind");
  return 1;
 }
 puts("Bind hecho");
 
 //LISTEN
 rtn = listen(listen_socket, 1); //1 es el maximo de conexiones a la vez
 cout << "Esperando conexiones entrantes en el puerto "<< PUERTO << "\n";
 /*if (rtn < 0) {
  perror("Error en el listen");
  return 1;
 }*/

 while (true) {

 sockaddr client;
 socklen_t c = sizeof(client);
 //ACCEPT
 cliente = accept(listen_socket, &client, &c);
 if (cliente < 0) {
  perror("Error en el accept");
  return 1;
 }
 cout << "Conexion aceptada en el puerto " << PUERTO << "\n";
 fflush(stdout);

 //READ
 char buffer[2000], bufferAux[2000];
//  cout << "Al menos intenta leer \n";
 bool noAcaba = true;
 while ((rtn = read(cliente, buffer, 2000)) > 0 && noAcaba) {
   cout << "Conectado en el puerto " << PUERTO << ". Esperando accion.\n";
//   cout << "RECIBIDO: " << buffer << "\n";
   if (!strcmp(buffer, "FIN")) {
    noAcaba = false;
   }
   else {
    fflush(stdout);
 //   cout << "Al menos lee \n";
 //   strcat(buffer, "  Servidor");
    for (int i = 0; i < rtn; i++) {
     buffer[i] = toupper(buffer[i]);
    }
    fflush(stdout);
    if (write(cliente, buffer, strlen(buffer)) < 0) {
     perror("Envio fallido");
     return 1;
    }
//    cout << "ENVIADO: " << buffer;
    fflush(stdout);
    //Reiniciarlo
    strcpy(buffer, "\0");
   }

   
  }
  if (rtn == 0) {
   cout << "Recibido FIN. \nCerrando la conexión con el cliente\n";
   cout<<"Cliente desconectado. Esperando conexion en el puerto "<< PUERTO << "\n";
   fflush(stdout);
  }
  else if (rtn == -1)
  {
   perror("Error en Read");
  }
  cout << "Esperando otro cliente.\n \n";

 }
 
 
 return 0;
}

Como podéis ver son algo extensos y programados de forma estructurada. De todos modos aquí teneis el proyecto en Git donde podréis ver los cambios así como otras dos posibilidades de crearlo llamadas "client2" y "server2".

Espero que os haya gustado. El contenido de éste post tiene relación con el "intento de chat" que aún está por acabar, pues ése empezó siendo un servidor de echo.

Saludos y hasta la próxima;)

No hay comentarios:

Publicar un comentario