#pragma comment(lib, "Ws2_32.lib") #include #include #include #include #include "Command.h" #pragma comment(lib, "Ws2_32.lib") const char* SERVER_IP = "127.0.0.1"; // Loopback - server is local const int SERVER_PORT = 8080; int main() { WSADATA wsaData; int result = WSAStartup(MAKEWORD(2, 2), &wsaData); if (result != 0) { std::cerr << "WSAStartup failed with error: " << result << std::endl; return 1; } SOCKET clientSocket = INVALID_SOCKET; struct addrinfo* info = nullptr; struct addrinfo hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; std::string portStr = std::to_string(SERVER_PORT); result = getaddrinfo(SERVER_IP, portStr.c_str(), &hints, &info); if (result != 0) { std::cerr << "getaddrinfo failed with error: " << result << std::endl; WSACleanup(); return 1; } clientSocket = socket(info->ai_family, info->ai_socktype, info->ai_protocol); if (clientSocket == INVALID_SOCKET) { std::cerr << "Error at socket(): " << WSAGetLastError() << std::endl; freeaddrinfo(info); WSACleanup(); return 1; } result = connect(clientSocket, info->ai_addr, (int)info->ai_addrlen); if (result == SOCKET_ERROR) { std::cerr << "Failed to connect to server: " << WSAGetLastError() << std::endl; closesocket(clientSocket); freeaddrinfo(info); WSACleanup(); return 1; } // Cleanup resolved address info, no longer needed freeaddrinfo(info); std::cout << "Successfully connected to server at " << SERVER_IP << ":" << SERVER_PORT << std::endl; std::cout << "Start typing commands (or type 'quit'):" << std::endl; std::string command; while (std::getline(std::cin, command) && command != "quit") { if (command.empty()) continue; int bytesSent = 0; // Split command to tokens std::vector tokens = {}; size_t pos = 0; while ((pos = command.find(' ')) != std::string::npos) { tokens.push_back(command.substr(0, pos)); command.erase(0, pos + 1); } tokens.push_back(command); if (tokens[0] == "list") { bytesSent = send(clientSocket, "LST1", 4, 0); } else if (tokens[0] == "score") { bytesSent = send(clientSocket, "GET1", 4, 0); } else if (tokens[0] == "mode") { char message[5] = "MOD1"; if (tokens.size() > 1) { message[4] = tokens[1][0]; } else { message[4] = '0'; // Default mode } bytesSent = send(clientSocket, message, 5, 0); } else if (tokens[0] == "select") { // Merge all tokens from 1 onward into a single name (in case it has spaces) std::string name; for (size_t i = 1; i < tokens.size(); i++) { if (i > 1) name += " "; name += tokens[i]; } name += ';'; Command c(Command::Type::TYPE_SELECT_NAME, { Command::Arg(name) }); size_t outSize = 0; char* serialized = c.Serialize(&outSize); int bytesSent = send(clientSocket, serialized, outSize, 0); delete[] serialized; } else if (tokens[0] == "getposition") { bytesSent = send(clientSocket, "POS1", 4, 0); } else if (tokens[0] == "translation") { Command c(Command::Type::TYPE_TRANSLATE, { Command::Arg(std::stof(tokens[1])), Command::Arg(std::stof(tokens[2])), Command::Arg(std::stof(tokens[3])) }); size_t outSize = 0; char* serialized = c.Serialize(&outSize); int bytesSent = send(clientSocket, serialized, outSize, 0); delete[] serialized; } else { std::cout << "Unknown command." << std::endl; continue; } if (bytesSent == SOCKET_ERROR) { std::cerr << "send failed: " << WSAGetLastError() << std::endl; break; } char recvbuf[1024]; int bytesRecv = recv(clientSocket, recvbuf, 1024, 0); if (bytesRecv > 0) { recvbuf[bytesRecv] = '\0'; std::cout << "Server Response: " << recvbuf; // C# server sends a newline, so no need to add one here. } else if (bytesRecv == 0) { std::cout << "Connection closed by server." << std::endl; break; } else { std::cerr << "recv failed: " << WSAGetLastError() << std::endl; break; } } closesocket(clientSocket); WSACleanup(); std::cout << "Client shut down." << std::endl; return 0; }