/
tytyshka
/
Typing_Race_Game
Обзор
Документация
Войти
/
tytyshka
/
Typing_Race_Game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
player_session.cpp
145 строк
4 KB
tytyshka
Client
16 дек 2025, 21:37
16 дек 2025, 21:37
f770ab5
Код
Авторство
О чём код?
#include "player_session.h" #include "dispatcher.h" #include "utils.h" #include <ws2tcpip.h> #include <iostream> #include <vector> #pragma comment(lib, "Ws2_32.lib") PlayerSession::PlayerSession(SOCKET sockfd, MessageDispatcher* dispatcher) : sockfd_(sockfd), dispatcher_(dispatcher) { } PlayerSession::~PlayerSession() { stop(); } void PlayerSession::start() { running_ = true; reader_thread_ = std::thread(&PlayerSession::reader_loop, this); processor_thread_ = std::thread(&PlayerSession::processor_loop, this); } void PlayerSession::stop() { if (!running_) return; running_ = false; shutdown(sockfd_, SD_BOTH); closesocket(sockfd_); in_cv_.notify_all(); if (reader_thread_.joinable()) reader_thread_.join(); if (processor_thread_.joinable()) processor_thread_.join(); } bool PlayerSession::send_json(const json& j) { std::lock_guard<std::mutex> send_lock(send_mtx_); if (!connected_) return false; std::string body = j.dump(); uint32_t len = (uint32_t)body.size(); char header[4]; write_be_u32(header, len); // send header int sent = 0; while (sent < 4) { int s = ::send(sockfd_, header + sent, 4 - sent, 0); if (s == SOCKET_ERROR) { std::cerr << "[PlayerSession] send header failed: " << WSAGetLastError() << "\n"; connected_ = false; return false; } sent += s; } // send body sent = 0; const char* data = body.data(); size_t to_send = body.size(); while (sent < (int)to_send) { int s = ::send(sockfd_, data + sent, (int)(to_send - sent), 0); if (s == SOCKET_ERROR) { std::cerr << "[PlayerSession] send body failed: " << WSAGetLastError() << "\n"; connected_ = false; return false; } sent += s; } return true; } void PlayerSession::enqueue_incoming(json j) { { std::lock_guard<std::mutex> lk(in_mtx_); incoming_.push(std::move(j)); } in_cv_.notify_one(); } PlayerInfo PlayerSession::get_info() { std::lock_guard<std::mutex> lk(info_mtx_); return info_; } void PlayerSession::set_info(const PlayerInfo& info) { std::lock_guard<std::mutex> lk(info_mtx_); info_ = info; } void PlayerSession::reader_loop() { while (running_) { // read 4-byte header char hdr[4]; int got = 0; while (got < 4) { int r = ::recv(sockfd_, hdr + got, 4 - got, 0); if (r == 0 || r == SOCKET_ERROR) { running_ = false; break; } got += r; } if (!running_) break; uint32_t len = read_be_u32(hdr); if (len == 0 || len > 10 * 1024 * 1024) { std::cerr << "[PlayerSession] invalid frame length: " << len << "\n"; running_ = false; break; } std::vector<char> buf(len); int received = 0; while (received < (int)len) { int n = ::recv(sockfd_, buf.data() + received, (int)(len - received), 0); if (n == 0 || n == SOCKET_ERROR) { running_ = false; break; } received += n; } if (!running_) break; try { std::string s(buf.begin(), buf.end()); json j = json::parse(s); enqueue_incoming(std::move(j)); } catch (std::exception& ex) { std::cerr << "[PlayerSession] JSON parse error: " << ex.what() << "\n"; } } in_cv_.notify_all(); } void PlayerSession::processor_loop() { while (running_) { json j; { std::unique_lock<std::mutex> lk(in_mtx_); in_cv_.wait(lk, [&] { return !incoming_.empty() || !running_; }); if (!running_ && incoming_.empty()) break; j = std::move(incoming_.front()); incoming_.pop(); } if (dispatcher_) { dispatcher_->dispatch(shared_from_this(), j); } } }