Underc0de - La Casa de los Informáticos

Programación General => C / C++ => Mensaje iniciado por: loris24 en Enero 08, 2026, 07:11:40 PM

Título: servidor y cliente tcp [simple]
Publicado por: loris24 en Enero 08, 2026, 07:11:40 PM
(https://i.postimg.cc/prTnQ6th/Server.png) (https://postimg.cc/R6kF4Gh4)

Buenas chicos.

Siguiendo la linea del hilo anterior os dejo por aqui mas codigo de redes.
En este caso son un simple cliente y servidor tcp.

El funcionamiento es sencillo. El cliente recoge mensajes por stdin y luego los envia al servidor, y éste, los imprime por pantalla.
Son codigos cortos escritos al momento, pensados para aprender mas que nada. Iré subiendo cada vez codigos mas complicados implementando funcionalidades mas complejas.


Este es el codigo del cliente:

#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <iostream>
#include <cstring>
#include <sys/select.h>



#define IP_SERVER ("127.0.0.1")
#define PORT ("9999")

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


    struct addrinfo base;
    memset(&base, 0, sizeof base);
    base.ai_socktype = SOCK_STREAM;
    struct addrinfo *res;

    if(getaddrinfo(IP_SERVER, PORT, &base, &res) < 0){
        std::cerr << "An error has ocurred with getaddrinfo" << std::endl;
        std::cerr << "exiting..." << std::endl;
        return -1;
    }

    int sock = socket(
        res -> ai_family,
        res -> ai_socktype,
        res -> ai_protocol
        );

    if(sock < 0){
        std::cerr << "Error creating socket" << std::endl;
        std::cerr << "exiting..." << std::endl;
        return -1;
    }

    if(connect(sock, res -> ai_addr, res -> ai_addrlen) < 0){
        std::cerr << "An error has ocurred while connecting to server" << std::endl;
        return -1;
    }

    freeaddrinfo(res);

    //ya podemos enviar y recibir !
    bool terminado = false;
    while(!terminado){ //cuidado! bucle infinito. Terminar con un CTRL+C

        fd_set out;
        FD_ZERO(&out);
        FD_SET(1, &out);
        int max_socket = 1;

        int res_select = select(max_socket + 1, &out, 0, 0, 0);
        //utilizamos select para probar si el descriptor stdin tiene entrada disponible

        if(res_select < 0){
            std::cerr << "An error has ocurred with select" << std::endl;
            return -1;
        }else{

            char buff[1024];
            if(!fgets(buff, 1024, stdin)) break;

            int bytes_sent = send(
                sock,
                buff,
                1024,
                0);
            if(bytes_sent <= 0){
                std::cout << "Connection closed by server" << std::endl;
                break;
            }else{
                std::cout << "Bytes sent:"<< bytes_sent << std::endl;
            }

        }

    }

    close(sock);

    return 0;
}


Este es el codigo del servidor:

#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <iostream>
#include <cstring>
#include <sys/select.h>
#include <cstdlib>



#define IP_SERVER NULL
/*
la definimos como nulo porque quiero que
el SO me asigne la direccion de loopback
*/

#define PORT_SERVER ("9999")

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


    struct addrinfo base;
    memset(&base, 0, sizeof base);
    base.ai_family = AF_INET;
    base.ai_socktype = SOCK_STREAM;
    base.ai_flags = AI_PASSIVE;
    struct addrinfo *res;

    if(getaddrinfo(IP_SERVER, PORT_SERVER, &base, &res) < 0){
        std::cerr << "An error has ocurred with getaddrinfo" << std::endl;
        std::cerr << "exiting..." << std::endl;
        return -1;
    }

    int sock_listen = socket(
        res -> ai_family,
        res -> ai_socktype,
        res -> ai_protocol
        );

    if(sock_listen < 0){
        std::cerr << "Error creating the socket to listen connections" << std::endl;
        std::cerr << "exiting..." << std::endl;
        return -1;
    }

    if(bind(sock_listen, res -> ai_addr, res -> ai_addrlen) < 0){
        std::cerr << "Error binding the ip to socket" << std::endl;
        std::cerr << "exiting..." << std::endl;
        return -1;
    }


    if(listen(sock_listen, 10) < 0){
        std::cerr << "An error has ocurred while listening to entry connections" << std::endl;
        return -1;
    }

    struct sockaddr_storage client_ip;
    socklen_t size_client = sizeof client_ip;

    int sock_peer = accept(

        sock_listen,
        (struct sockaddr *)&client_ip,
        &size_client
        );

    //accept nos devuelve el socket por el que 'hablaremos' con la conexion entrante


    if(sock_peer < 0){
        std::cerr << "An error has ocurred while accepting socket" << std::endl;
        return -1;
    }

    //ya podemos hablar con a traves de sock_peer
    //imprimimos a continuacion la ip del host que se acaba de conectar

    char buff_host[128];
    char buff_port[128];

    getnameinfo(
        (struct sockaddr *)&client_ip,
        size_client,
        buff_host,
        128,
        buff_port,
        128,
        NI_NUMERICHOST | NI_NUMERICSERV
        );

    std::cout << "Host connected:" << std::endl;
    std::cout << "Ip:"<< buff_host << std::endl;
    std::cout << "Port:" << buff_port << std::endl;



    bool terminado = false;
    while(!terminado){ //cuidado, parar bucle con CTRL+C

        //aqui es donde recibimos e imprimimos el mensaje
        char buff_recv[1024];
        int bytes_received = recv(sock_peer,
            buff_recv,
            1024,
            0);

        if(bytes_received == 0){
            std::cout << "Connection closed by host" << std::endl;
            break;
        }

        if(bytes_received < 0){
            std::cout << "Connection error" << std::endl;
            break;
        }
        printf("%.*s\n", bytes_received, buff_recv);

    }
    close(sock_listen);
    return 0;

}