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;)