MetaCore/tools/MetaCoreTcpSenderTool/main.cpp
2026-06-02 09:19:17 +08:00

165 lines
5.4 KiB
C++

#include <chrono>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
namespace {
using MetaCoreSocketLength =
#if defined(_WIN32)
int;
using MetaCoreSocket = SOCKET;
constexpr MetaCoreSocket MetaCoreInvalidSocket = INVALID_SOCKET;
constexpr int MetaCoreSocketError = SOCKET_ERROR;
constexpr int MetaCoreShutdownSend = SD_SEND;
#else
socklen_t;
using MetaCoreSocket = int;
constexpr MetaCoreSocket MetaCoreInvalidSocket = -1;
constexpr int MetaCoreSocketError = -1;
constexpr int MetaCoreShutdownSend = SHUT_WR;
#endif
bool MetaCoreInitializeSocketApi() {
#if defined(_WIN32)
WSADATA wsaData{};
return WSAStartup(MAKEWORD(2, 2), &wsaData) == 0;
#else
return true;
#endif
}
void MetaCoreShutdownSocketApi() {
#if defined(_WIN32)
WSACleanup();
#endif
}
void MetaCoreCloseSocket(MetaCoreSocket socketHandle) {
if (socketHandle == MetaCoreInvalidSocket) {
return;
}
#if defined(_WIN32)
closesocket(socketHandle);
#else
close(socketHandle);
#endif
}
} // namespace
int main(int argc, char* argv[]) {
const std::string bindHost = argc > 1 ? argv[1] : "127.0.0.1";
const unsigned short port = argc > 2 ? static_cast<unsigned short>(std::strtoul(argv[2], nullptr, 10)) : 7001;
if (!MetaCoreInitializeSocketApi()) {
std::cerr << "MetaCoreTcpSenderTool: socket API initialization failed\n";
return 1;
}
addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
addrinfo* result = nullptr;
const std::string portString = std::to_string(port);
if (getaddrinfo(bindHost.c_str(), portString.c_str(), &hints, &result) != 0 || result == nullptr) {
std::cerr << "MetaCoreTcpSenderTool: getaddrinfo failed\n";
MetaCoreShutdownSocketApi();
return 1;
}
MetaCoreSocket listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == MetaCoreInvalidSocket) {
std::cerr << "MetaCoreTcpSenderTool: socket creation failed\n";
freeaddrinfo(result);
MetaCoreShutdownSocketApi();
return 1;
}
if (bind(listenSocket, result->ai_addr, static_cast<MetaCoreSocketLength>(result->ai_addrlen)) == MetaCoreSocketError) {
std::cerr << "MetaCoreTcpSenderTool: bind failed\n";
MetaCoreCloseSocket(listenSocket);
freeaddrinfo(result);
MetaCoreShutdownSocketApi();
return 1;
}
freeaddrinfo(result);
if (listen(listenSocket, 1) == MetaCoreSocketError) {
std::cerr << "MetaCoreTcpSenderTool: listen failed\n";
MetaCoreCloseSocket(listenSocket);
MetaCoreShutdownSocketApi();
return 1;
}
std::cout << "MetaCoreTcpSenderTool: listening on " << bindHost << ":" << port << '\n';
MetaCoreSocket clientSocket = accept(listenSocket, nullptr, nullptr);
MetaCoreCloseSocket(listenSocket);
if (clientSocket == MetaCoreInvalidSocket) {
std::cerr << "MetaCoreTcpSenderTool: accept failed\n";
MetaCoreShutdownSocketApi();
return 1;
}
std::cout << "MetaCoreTcpSenderTool: client connected\n";
for (int frame = 0; frame < 600; ++frame) {
const double t = static_cast<double>(frame) * 0.05;
const float x = static_cast<float>(std::sin(t) * 2.0);
const bool visible = std::fmod(t, 2.0) < 1.0;
const bool valveVisible = std::fmod(t, 3.0) < 1.5;
const float r = 0.5F + static_cast<float>(std::sin(t) * 0.4);
const float g = 0.6F;
const float b = 0.9F - static_cast<float>(std::sin(t) * 0.2);
const float tankR = 0.25F + static_cast<float>((std::sin(t * 0.5) + 1.0) * 0.25);
const float tankG = 0.55F + static_cast<float>((std::cos(t * 0.5) + 1.0) * 0.15);
const float tankB = 0.35F;
const double alarmIntensity = valveVisible ? 2.5 : 0.0;
const std::string payload =
"cube.position vec3 " + std::to_string(x) + " 0.5 0.0\n" +
"cube.visible bool " + std::string(visible ? "true" : "false") + "\n" +
"cube.base_color vec3 " + std::to_string(r) + " " + std::to_string(g) + " " + std::to_string(b) + "\n" +
"valve.visible bool " + std::string(valveVisible ? "true" : "false") + "\n" +
"tank.base_color vec3 " + std::to_string(tankR) + " " + std::to_string(tankG) + " " + std::to_string(tankB) + "\n" +
"alarm.intensity double " + std::to_string(alarmIntensity) + "\n";
const auto sent = send(clientSocket, payload.c_str(), static_cast<MetaCoreSocketLength>(payload.size()), 0);
if (sent == MetaCoreSocketError) {
std::cerr << "MetaCoreTcpSenderTool: send failed\n";
MetaCoreCloseSocket(clientSocket);
MetaCoreShutdownSocketApi();
return 1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
shutdown(clientSocket, MetaCoreShutdownSend);
MetaCoreCloseSocket(clientSocket);
MetaCoreShutdownSocketApi();
std::cout << "MetaCoreTcpSenderTool: stream completed\n";
return 0;
}