Servidor y cliente en C++ con winshock2 (Chat Lan)

Iniciado por kukuruznom, Junio 20, 2023, 01:08:48 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Hola, tengo un problema, bueno, muchos problemas con Winsock. Ya he programado algo similar una vez en Linux y no me pareció tan complicado. El problema es que ahora, aunque el servidor compila correctamente, no reenvía los mensajes, o no sé qué es lo que realmente está funcionando mal.
Obtuve gran parte de la información de aquí: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login.
Intenté utilizar ChatGPT y Perplexity, pero tampoco resolvieron nada.
Encontré esto, pero es de hace más de diez años: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login.
Y lo que encontré que sí funciona es para Linux.
A continuacion les dejo mi codigo:
server:
Código: text
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>
#include <vector>
#include <memory>

#pragma comment(lib, "ws2_32.lib")

#define DEFAULT_BUFLEN 512

using namespace std;

int main() {
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        cerr << "WSAStartup falló: " << iResult << endl;
        return 1;
    }

    string ipAddress;
    string port;

    cout << "Ingrese la dirección IP del servidor: ";
    cin >> ipAddress;

    cout << "Ingrese el puerto del servidor: ";
    cin >> port;

    struct addrinfo* result = NULL;
    struct addrinfo hints;

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    iResult = getaddrinfo(ipAddress.c_str(), port.c_str(), &hints, &result);
    if (iResult != 0) {
        cerr << "getaddrinfo falló: " << iResult << endl;
        WSACleanup();
        return 1;
    }

    SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        cerr << "Error en socket(): " << WSAGetLastError() << endl;
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        cerr << "bind falló con error: " << WSAGetLastError() << endl;
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        cerr << "listen falló con error: " << WSAGetLastError() << endl;
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    cout << "Servidor iniciado. Esperando conexiones en " << ipAddress << ":" << port << "..." << endl;

    vector<unique_ptr<SOCKET>> clientSockets;

    while (true) {
        SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
        if (ClientSocket == INVALID_SOCKET) {
            cerr << "accept falló: " << WSAGetLastError() << endl;
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }

        clientSockets.push_back(make_unique<SOCKET>(ClientSocket));

        cout << "Cliente conectado." << endl;

        string nickname;
        char recvbuf[DEFAULT_BUFLEN];
        int iSendResult;

        iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
        if (iResult > 0) {
            recvbuf[iResult] = '\0';
            nickname = recvbuf;
            cout << "Nickname del cliente: " << nickname << endl;
        }

        for (auto it = clientSockets.begin(); it != clientSockets.end(); ++it) {
            if (**it != ClientSocket) {
                string message = nickname + " se ha conectado.";
                iSendResult = send(**it, message.c_str(), message.size(), 0);
                if (iSendResult == SOCKET_ERROR) {
                    cerr << "send falló: " << WSAGetLastError() << endl;
                    closesocket(**it);
                    clientSockets.erase(it);
                }
            }
        }

        while (true) {
            iResult = recv(ClientSocket, recvbuf, DEFAULT_BUFLEN, 0);
            if (iResult > 0) {
                recvbuf[iResult] = '\0';
                string message = nickname + ": " + recvbuf;
                for (auto it = clientSockets.begin(); it != clientSockets.end(); ++it) {
                    if (**it != ClientSocket) {
                        iSendResult = send(**it, message.c_str(), message.size(), 0);
                        if (iSendResult == SOCKET_ERROR) {
                            cerr << "send falló: " << WSAGetLastError() << endl;
                            closesocket(**it);
                            clientSockets.erase(it);
                        }
                    }
                }
            }
            else if (iResult == 0) {
                cout << "Cliente desconectado." << endl;
                for (auto it = clientSockets.begin(); it != clientSockets.end(); ++it) {
                    if (**it != ClientSocket) {
                        string message = nickname + " se ha desconectado.";
                        iSendResult = send(**it, message.c_str(), message.size(), 0);
                        if (iSendResult == SOCKET_ERROR) {
                            cerr << "send falló: " << WSAGetLastError() << endl;
                            closesocket(**it);
                            clientSockets.erase(it);
                        }
                    }
                }
                closesocket(ClientSocket);
                break;
            }
            else {
                cerr << "recv falló: " << WSAGetLastError() << endl;
                closesocket(ClientSocket);
                break;
            }
        }
    }

    WSACleanup();
    return 0;
}
cliente
Código: text
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <string>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main(int argc, char* argv[]) {
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        cerr << "WSAStartup falló: " << iResult << endl;
        return 1;
    }

    struct addrinfo* result = NULL, * ptr = NULL, hints;

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    string serverIP;
    cout << "Ingrese la IP del servidor: ";
    cin >> serverIP;

    string port;
    cout << "Ingrese el puerto: ";
    cin >> port;

    string nickname;
    cout << "Ingrese el apodo: ";
    cin >> nickname;

    iResult = getaddrinfo(serverIP.c_str(), port.c_str(), &hints, &result);
    if (iResult != 0) {
        cerr << "getaddrinfo falló: " << iResult << endl;
        WSACleanup();
        return 1;
    }

    SOCKET ConnectSocket = INVALID_SOCKET;
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            cerr << "Error en socket(): " << WSAGetLastError() << endl;
            freeaddrinfo(result);
            WSACleanup();
            return 1;
        }

        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        cerr << "¡No se pudo conectar al servidor!" << endl;
        WSACleanup();
        return 1;
    }

    cout << "Conectado al servidor." << endl;

    iResult = send(ConnectSocket, nickname.c_str(), nickname.size(), 0);
    if (iResult == SOCKET_ERROR) {
        cerr << "send falló: " << WSAGetLastError() << endl;
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    char recvbuf[512];
    int iSendResult;

    while (true) {
        string message;
        getline(cin, message);
        message = nickname + ": " + message;
        iResult = send(ConnectSocket, message.c_str(), message.size(), 0);
        if (iResult == SOCKET_ERROR) {
            cerr << "send falló: " << WSAGetLastError() << endl;
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
    }

    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        cerr << "shutdown falló: " << WSAGetLastError() << endl;
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
Si alguien conoce otra forma de hacerlo sin Winsock o lo ha hecho antes, estaría agradecido si pudiera ver cómo lo hicieron.
En la oscuridad de la incertidumbre, nace el poder de la determinación.