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í: https://learn.microsoft.com/pdf?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fapi%2Fwinsock2%2Ftoc.json (https://learn.microsoft.com/pdf?url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fwindows%2Fwin32%2Fapi%2Fwinsock2%2Ftoc.json).
Intenté utilizar ChatGPT y Perplexity, pero tampoco resolvieron nada.
Encontré esto, pero es de hace más de diez años: https://github.com/fffaraz/Lan-Messenger (https://github.com/fffaraz/Lan-Messenger).
Y lo que encontré que sí funciona es para Linux.
A continuacion les dejo mi codigo:
server:
#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
#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.
(https://imgur.com/iX8fkFa)