Major clean up
This commit is contained in:
1 parent
6aff22ec53
commit
1a7e424085
16 files changed
+390
-490
No files matched your search
@@ -0,0 +1,224 @@
|
||||
#include "ClientState.h"
|
||||
|
||||
|
||||
void ClientState::simulate_physics(size_t delta) {
|
||||
if (discreteMag > 0.01f)
|
||||
{
|
||||
float rad = static_cast<float>(discreteAngle) * static_cast<float>(M_PI) / 180.0f;
|
||||
|
||||
// Целевая угловая скорость (дискретная сила определяет модуль вектора)
|
||||
// Вектор {cos, sin, 0} дает нам направление отклонения джойстика
|
||||
Eigen::Vector3f targetAngularVelDir(sinf(rad), cosf(rad), 0.0f);
|
||||
Eigen::Vector3f targetAngularVelocity = targetAngularVelDir * discreteMag;
|
||||
|
||||
Eigen::Vector3f diffVel = targetAngularVelocity - currentAngularVelocity;
|
||||
float diffLen = diffVel.norm();
|
||||
|
||||
if (diffLen > 0.0001f) {
|
||||
// Вычисляем, на сколько мы можем изменить скорость в этом кадре
|
||||
float maxChange = ANGULAR_ACCEL * static_cast<float>(delta);
|
||||
|
||||
if (diffLen <= maxChange) {
|
||||
// Если до цели осталось меньше, чем шаг ускорения — просто прыгаем в цель
|
||||
currentAngularVelocity = targetAngularVelocity;
|
||||
}
|
||||
|
||||
else {
|
||||
// Линейно двигаемся в сторону целевого вектора
|
||||
currentAngularVelocity += (diffVel / diffLen) * maxChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float currentSpeed = currentAngularVelocity.norm();
|
||||
|
||||
if (currentSpeed > 0.0001f) {
|
||||
float drop = ANGULAR_ACCEL * static_cast<float>(delta);
|
||||
if (currentSpeed <= drop) {
|
||||
currentAngularVelocity = Eigen::Vector3f::Zero();
|
||||
}
|
||||
else {
|
||||
// Уменьшаем модуль вектора, сохраняя направление
|
||||
currentAngularVelocity -= (currentAngularVelocity / currentSpeed) * drop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float speedScale = currentAngularVelocity.norm();
|
||||
if (speedScale > 0.0001f) {
|
||||
// Коэффициент чувствительности вращения
|
||||
|
||||
float deltaAlpha = speedScale * static_cast<float>(delta) * ROTATION_SENSITIVITY;
|
||||
|
||||
Eigen::Vector3f axis = currentAngularVelocity.normalized();
|
||||
Eigen::Quaternionf rotateQuat(Eigen::AngleAxisf(deltaAlpha, axis));
|
||||
|
||||
rotation = rotation * rotateQuat.toRotationMatrix();
|
||||
}
|
||||
|
||||
|
||||
// 4. Линейное изменение линейной скорости
|
||||
float shipDesiredVelocity = selectedVelocity * 100.f;
|
||||
|
||||
if (velocity < shipDesiredVelocity)
|
||||
{
|
||||
velocity += delta * SHIP_ACCEL;
|
||||
if (velocity > shipDesiredVelocity)
|
||||
{
|
||||
velocity = shipDesiredVelocity;
|
||||
}
|
||||
}
|
||||
else if (velocity > shipDesiredVelocity)
|
||||
{
|
||||
velocity -= delta * SHIP_ACCEL;
|
||||
if (velocity < shipDesiredVelocity)
|
||||
{
|
||||
velocity = shipDesiredVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
if (fabs(velocity) > 0.01f)
|
||||
{
|
||||
Eigen::Vector3f velocityDirection = { 0,0, -velocity * delta / 1000.f };
|
||||
Eigen::Vector3f velocityDirectionAdjusted = rotation * velocityDirection;
|
||||
position = position + velocityDirectionAdjusted;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientState::apply_lag_compensation(std::chrono::system_clock::time_point nowTime) {
|
||||
|
||||
// 2. Вычисляем задержку
|
||||
long long deltaMs = 0;
|
||||
if (nowTime > lastUpdateServerTime) {
|
||||
deltaMs = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime - lastUpdateServerTime).count();
|
||||
}
|
||||
|
||||
// 3. Защита от слишком больших скачков (Clamp)
|
||||
// Если лаг более 500мс, ограничиваем его, чтобы избежать резких рывков
|
||||
long long final_lag_ms = deltaMs;//min(deltaMs, 500ll);
|
||||
|
||||
if (final_lag_ms > 0) {
|
||||
// Доматываем симуляцию на величину задержки
|
||||
// Мы предполагаем, что за это время параметры управления не менялись
|
||||
simulate_physics(final_lag_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientState::handle_full_sync(const std::vector<std::string>& parts, int startFrom) {
|
||||
// Позиция
|
||||
position = { std::stof(parts[startFrom]), std::stof(parts[startFrom + 1]), std::stof(parts[startFrom + 2]) };
|
||||
|
||||
Eigen::Quaternionf q(
|
||||
std::stof(parts[startFrom + 3]),
|
||||
std::stof(parts[startFrom + 4]),
|
||||
std::stof(parts[startFrom + 5]),
|
||||
std::stof(parts[startFrom + 6]));
|
||||
rotation = q.toRotationMatrix();
|
||||
|
||||
currentAngularVelocity = Eigen::Vector3f{
|
||||
std::stof(parts[startFrom + 7]),
|
||||
std::stof(parts[startFrom + 8]),
|
||||
std::stof(parts[startFrom + 9]) };
|
||||
velocity = std::stof(parts[startFrom + 10]);
|
||||
selectedVelocity = std::stoi(parts[startFrom + 11]);
|
||||
discreteMag = std::stof(parts[startFrom + 12]);
|
||||
discreteAngle = std::stoi(parts[startFrom + 13]);
|
||||
}
|
||||
|
||||
std::string ClientState::formPingMessageContent()
|
||||
{
|
||||
Eigen::Quaternionf q(rotation);
|
||||
|
||||
std::string pingMsg = std::to_string(position.x()) + ":"
|
||||
+ std::to_string(position.y()) + ":"
|
||||
+ std::to_string(position.z()) + ":"
|
||||
+ std::to_string(q.w()) + ":"
|
||||
+ std::to_string(q.x()) + ":"
|
||||
+ std::to_string(q.y()) + ":"
|
||||
+ std::to_string(q.z()) + ":"
|
||||
+ std::to_string(currentAngularVelocity.x()) + ":"
|
||||
+ std::to_string(currentAngularVelocity.y()) + ":"
|
||||
+ std::to_string(currentAngularVelocity.z()) + ":"
|
||||
+ std::to_string(velocity) + ":"
|
||||
+ std::to_string(selectedVelocity) + ":"
|
||||
+ std::to_string(discreteMag) + ":" // Используем те же static переменные из блока ROT
|
||||
+ std::to_string(discreteAngle);
|
||||
|
||||
return pingMsg;
|
||||
}
|
||||
|
||||
|
||||
void ClientStateInterval::add_state(const ClientState& state)
|
||||
{
|
||||
auto nowTime = std::chrono::system_clock::now();
|
||||
|
||||
if (timedStates.size() > 0 && timedStates[timedStates.size() - 1].lastUpdateServerTime == state.lastUpdateServerTime)
|
||||
{
|
||||
timedStates[timedStates.size() - 1] = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
timedStates.push_back(state);
|
||||
}
|
||||
|
||||
auto cutoff_time = nowTime - std::chrono::milliseconds(CUTOFF_TIME);
|
||||
|
||||
while (timedStates.size() > 0 && timedStates[0].lastUpdateServerTime < cutoff_time)
|
||||
{
|
||||
timedStates.erase(timedStates.begin());
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientStateInterval::canFetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const
|
||||
{
|
||||
if (timedStates.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (timedStates[0].lastUpdateServerTime > targetTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ClientState ClientStateInterval::fetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const {
|
||||
|
||||
ClientState closestState;
|
||||
|
||||
if (timedStates.empty())
|
||||
{
|
||||
throw std::runtime_error("No timed client states available");
|
||||
return closestState;
|
||||
}
|
||||
if (timedStates[0].lastUpdateServerTime > targetTime)
|
||||
{
|
||||
throw std::runtime_error("Found time but it is in future");
|
||||
return closestState;
|
||||
}
|
||||
if (timedStates.size() == 1)
|
||||
{
|
||||
closestState = timedStates[0];
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < timedStates.size() - 1; ++i)
|
||||
{
|
||||
const auto& earlierState = timedStates[i];
|
||||
const auto& laterState = timedStates[i + 1];
|
||||
if (earlierState.lastUpdateServerTime <= targetTime && laterState.lastUpdateServerTime >= targetTime)
|
||||
{
|
||||
closestState = earlierState;
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
}
|
||||
|
||||
closestState = timedStates[timedStates.size() - 1];
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
+9
-194
@@ -25,213 +25,28 @@ struct ClientState {
|
||||
float velocity = 0.0f;
|
||||
int selectedVelocity = 0;
|
||||
float discreteMag = 0;
|
||||
int discreteAngle = -1;
|
||||
int discreteAngle = -1;
|
||||
|
||||
// Для расчета лага
|
||||
std::chrono::system_clock::time_point lastUpdateServerTime;
|
||||
|
||||
void simulate_physics(size_t delta) {
|
||||
if (discreteMag > 0.01f)
|
||||
{
|
||||
float rad = static_cast<float>(discreteAngle) * static_cast<float>(M_PI) / 180.0f;
|
||||
void simulate_physics(size_t delta);
|
||||
|
||||
// Целевая угловая скорость (дискретная сила определяет модуль вектора)
|
||||
// Вектор {cos, sin, 0} дает нам направление отклонения джойстика
|
||||
Eigen::Vector3f targetAngularVelDir(sinf(rad), cosf(rad), 0.0f);
|
||||
Eigen::Vector3f targetAngularVelocity = targetAngularVelDir * discreteMag;
|
||||
void apply_lag_compensation(std::chrono::system_clock::time_point nowTime);
|
||||
|
||||
Eigen::Vector3f diffVel = targetAngularVelocity - currentAngularVelocity;
|
||||
float diffLen = diffVel.norm();
|
||||
void handle_full_sync(const std::vector<std::string>& parts, int startFrom);
|
||||
|
||||
if (diffLen > 0.0001f) {
|
||||
// Вычисляем, на сколько мы можем изменить скорость в этом кадре
|
||||
float maxChange = ANGULAR_ACCEL * static_cast<float>(delta);
|
||||
|
||||
if (diffLen <= maxChange) {
|
||||
// Если до цели осталось меньше, чем шаг ускорения — просто прыгаем в цель
|
||||
currentAngularVelocity = targetAngularVelocity;
|
||||
}
|
||||
|
||||
else {
|
||||
// Линейно двигаемся в сторону целевого вектора
|
||||
currentAngularVelocity += (diffVel / diffLen) * maxChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float currentSpeed = currentAngularVelocity.norm();
|
||||
|
||||
if (currentSpeed > 0.0001f) {
|
||||
float drop = ANGULAR_ACCEL * static_cast<float>(delta);
|
||||
if (currentSpeed <= drop) {
|
||||
currentAngularVelocity = Eigen::Vector3f::Zero();
|
||||
}
|
||||
else {
|
||||
// Уменьшаем модуль вектора, сохраняя направление
|
||||
currentAngularVelocity -= (currentAngularVelocity / currentSpeed) * drop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float speedScale = currentAngularVelocity.norm();
|
||||
if (speedScale > 0.0001f) {
|
||||
// Коэффициент чувствительности вращения
|
||||
|
||||
float deltaAlpha = speedScale * static_cast<float>(delta) * ROTATION_SENSITIVITY;
|
||||
|
||||
Eigen::Vector3f axis = currentAngularVelocity.normalized();
|
||||
Eigen::Quaternionf rotateQuat(Eigen::AngleAxisf(deltaAlpha, axis));
|
||||
|
||||
rotation = rotation * rotateQuat.toRotationMatrix();
|
||||
}
|
||||
|
||||
|
||||
// 4. Линейное изменение линейной скорости
|
||||
float shipDesiredVelocity = selectedVelocity * 100.f;
|
||||
|
||||
if (velocity < shipDesiredVelocity)
|
||||
{
|
||||
velocity += delta * SHIP_ACCEL;
|
||||
if (velocity > shipDesiredVelocity)
|
||||
{
|
||||
velocity = shipDesiredVelocity;
|
||||
}
|
||||
}
|
||||
else if (velocity > shipDesiredVelocity)
|
||||
{
|
||||
velocity -= delta * SHIP_ACCEL;
|
||||
if (velocity < shipDesiredVelocity)
|
||||
{
|
||||
velocity = shipDesiredVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
if (fabs(velocity) > 0.01f)
|
||||
{
|
||||
Eigen::Vector3f velocityDirection = { 0,0, -velocity * delta / 1000.f };
|
||||
Eigen::Vector3f velocityDirectionAdjusted = rotation * velocityDirection;
|
||||
position = position + velocityDirectionAdjusted;
|
||||
}
|
||||
}
|
||||
|
||||
void apply_lag_compensation(std::chrono::system_clock::time_point nowTime) {
|
||||
|
||||
// 2. Вычисляем задержку
|
||||
long long deltaMs = 0;
|
||||
if (nowTime > lastUpdateServerTime) {
|
||||
deltaMs = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime - lastUpdateServerTime).count();
|
||||
}
|
||||
|
||||
// 3. Защита от слишком больших скачков (Clamp)
|
||||
// Если лаг более 500мс, ограничиваем его, чтобы избежать резких рывков
|
||||
long long final_lag_ms = deltaMs;//min(deltaMs, 500ll);
|
||||
|
||||
if (final_lag_ms > 0) {
|
||||
// Доматываем симуляцию на величину задержки
|
||||
// Мы предполагаем, что за это время параметры управления не менялись
|
||||
simulate_physics(final_lag_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_full_sync(const std::vector<std::string>& parts, int startFrom) {
|
||||
// Позиция
|
||||
position = { std::stof(parts[startFrom]), std::stof(parts[startFrom+1]), std::stof(parts[startFrom+2]) };
|
||||
|
||||
Eigen::Quaternionf q(
|
||||
std::stof(parts[startFrom+3]),
|
||||
std::stof(parts[startFrom+4]),
|
||||
std::stof(parts[startFrom+5]),
|
||||
std::stof(parts[startFrom+6]));
|
||||
rotation = q.toRotationMatrix();
|
||||
|
||||
currentAngularVelocity = Eigen::Vector3f{
|
||||
std::stof(parts[startFrom+7]),
|
||||
std::stof(parts[startFrom+8]),
|
||||
std::stof(parts[startFrom+9]) };
|
||||
velocity = std::stof(parts[startFrom+10]);
|
||||
selectedVelocity = std::stoi(parts[startFrom+11]);
|
||||
discreteMag = std::stof(parts[startFrom+12]);
|
||||
discreteAngle = std::stoi(parts[startFrom+13]);
|
||||
}
|
||||
std::string formPingMessageContent();
|
||||
};
|
||||
|
||||
|
||||
struct ClientStateInterval
|
||||
{
|
||||
std::vector<ClientState> timedStates;
|
||||
|
||||
void add_state(const ClientState& state)
|
||||
{
|
||||
auto nowTime = std::chrono::system_clock::now();
|
||||
void add_state(const ClientState& state);
|
||||
|
||||
if (timedStates.size() > 0 && timedStates[timedStates.size() - 1].lastUpdateServerTime == state.lastUpdateServerTime)
|
||||
{
|
||||
timedStates[timedStates.size() - 1] = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
timedStates.push_back(state);
|
||||
}
|
||||
bool canFetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const;
|
||||
|
||||
auto cutoff_time = nowTime - std::chrono::milliseconds(CUTOFF_TIME);
|
||||
|
||||
while (timedStates.size() > 0 && timedStates[0].lastUpdateServerTime < cutoff_time)
|
||||
{
|
||||
timedStates.erase(timedStates.begin());
|
||||
}
|
||||
}
|
||||
|
||||
bool canFetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const
|
||||
{
|
||||
if (timedStates.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (timedStates[0].lastUpdateServerTime > targetTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ClientState fetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const {
|
||||
|
||||
ClientState closestState;
|
||||
|
||||
if (timedStates.empty())
|
||||
{
|
||||
throw std::runtime_error("No timed client states available");
|
||||
return closestState;
|
||||
}
|
||||
if (timedStates[0].lastUpdateServerTime > targetTime)
|
||||
{
|
||||
throw std::runtime_error("Found time but it is in future");
|
||||
return closestState;
|
||||
}
|
||||
if (timedStates.size() == 1)
|
||||
{
|
||||
closestState = timedStates[0];
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < timedStates.size() - 1; ++i)
|
||||
{
|
||||
const auto& earlierState = timedStates[i];
|
||||
const auto& laterState = timedStates[i + 1];
|
||||
if (earlierState.lastUpdateServerTime <= targetTime && laterState.lastUpdateServerTime >= targetTime)
|
||||
{
|
||||
closestState = earlierState;
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
}
|
||||
|
||||
closestState = timedStates[timedStates.size() - 1];
|
||||
closestState.apply_lag_compensation(targetTime);
|
||||
return closestState;
|
||||
}
|
||||
ClientState fetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "ClientState.h"
|
||||
|
||||
// NetworkInterface.h - Èíòåðôåéñ äëÿ ðàçíûõ òèïîâ ñîåäèíåíèé
|
||||
// NetworkInterface.h - »нтерфейс дл¤ разных типов соединений
|
||||
namespace ZL {
|
||||
|
||||
class INetworkClient {
|
||||
@@ -13,7 +13,7 @@ namespace ZL {
|
||||
virtual void Connect(const std::string& host, uint16_t port) = 0;
|
||||
virtual void Send(const std::string& message) = 0;
|
||||
virtual bool IsConnected() const = 0;
|
||||
virtual void Poll() = 0; // Äëÿ îáðàáîòêè âõîäÿùèõ ïàêåòîâ
|
||||
virtual void Poll() = 0; // ƒл¤ обработки вход¤щих пакетов
|
||||
virtual std::unordered_map<int, ClientStateInterval> getRemotePlayers() = 0;
|
||||
};
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#pragma once
|
||||
#include "ClientState.h"
|
||||
@@ -1,9 +1,8 @@
|
||||
#include "WebSocketClient.h"
|
||||
#include "WebSocketClient.h"
|
||||
#include <iostream>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "RemotePlayer.h"
|
||||
|
||||
// Âñïîìîãàòåëüíûé split
|
||||
// Вспомогательный split
|
||||
std::vector<std::string> split(const std::string& s, char delimiter) {
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
@@ -23,13 +22,13 @@ namespace ZL {
|
||||
|
||||
ws_ = std::make_unique<boost::beast::websocket::stream<boost::beast::tcp_stream>>(ioc_);
|
||||
|
||||
// Âûïîëíÿåì ñèíõðîííûé êîííåêò è handshake äëÿ ïðîñòîòû ñòàðòà
|
||||
// Выполняем синхронный коннект и handshake для простоты старта
|
||||
boost::beast::get_lowest_layer(*ws_).connect(results);
|
||||
ws_->handshake(host, "/");
|
||||
|
||||
connected = true;
|
||||
|
||||
// Çàïóñêàåì àñèíõðîííîå ÷òåíèå â ïóëå ïîòîêîâ TaskManager
|
||||
// Запускаем асинхронное чтение в пуле потоков TaskManager
|
||||
startAsyncRead();
|
||||
|
||||
}
|
||||
@@ -53,12 +52,12 @@ namespace ZL {
|
||||
}
|
||||
|
||||
void WebSocketClient::processIncomingMessage(const std::string& msg) {
|
||||
// Ëîãèêà ïàðñèíãà...
|
||||
// Логика парсинга...
|
||||
if (msg.rfind("ID:", 0) == 0) {
|
||||
clientId = std::stoi(msg.substr(3));
|
||||
}
|
||||
|
||||
// Áåçîïàñíî êëàäåì â î÷åðåäü äëÿ ãëàâíîãî ïîòîêà
|
||||
// Безопасно кладем в очередь для главного потока
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
messageQueue.push(msg);
|
||||
}
|
||||
@@ -138,14 +137,14 @@ namespace ZL {
|
||||
std::lock_guard<std::mutex> lock(writeMutex_);
|
||||
writeQueue_.push(ss);
|
||||
|
||||
// Åñëè ñåé÷àñ íè÷åãî íå çàïèñûâàåòñÿ, èíèöèèðóåì ïåðâóþ çàïèñü
|
||||
// Если сейчас ничего не записывается, инициируем первую запись
|
||||
if (!isWriting_) {
|
||||
doWrite();
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketClient::doWrite() {
|
||||
// Ýòà ôóíêöèÿ âñåãäà âûçûâàåòñÿ ïîä ìüþòåêñîì èëè èç êîëáýêà
|
||||
// Эта функция всегда вызывается под мьютексом или из колбэка
|
||||
if (writeQueue_.empty()) {
|
||||
isWriting_ = false;
|
||||
return;
|
||||
@@ -154,7 +153,7 @@ namespace ZL {
|
||||
isWriting_ = true;
|
||||
auto message = writeQueue_.front();
|
||||
|
||||
// Çàõâàòûâàåì self (shared_from_this), ÷òîáû îáúåêò íå óäàëèëñÿ âî âðåìÿ çàïèñè
|
||||
// Захватываем self (shared_from_this), чтобы объект не удалился во время записи
|
||||
ws_->async_write(
|
||||
boost::asio::buffer(*message),
|
||||
[this, message](boost::beast::error_code ec, std::size_t) {
|
||||
@@ -164,8 +163,8 @@ namespace ZL {
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(writeMutex_);
|
||||
writeQueue_.pop(); // Óäàëÿåì îòïðàâëåííîå ñîîáùåíèå
|
||||
doWrite(); // Ïðîâåðÿåì ñëåäóþùåå
|
||||
writeQueue_.pop(); // Удаляем отправленное сообщение
|
||||
doWrite(); // Проверяем следующее
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
// WebSocketClient.h
|
||||
#include "NetworkInterface.h"
|
||||
@@ -12,19 +12,19 @@ namespace ZL {
|
||||
|
||||
class WebSocketClient : public INetworkClient {
|
||||
private:
|
||||
// Ïåðåèñïîëüçóåì io_context èç TaskManager
|
||||
// Переиспользуем io_context из TaskManager
|
||||
boost::asio::io_context& ioc_;
|
||||
|
||||
// Îáúåêòû ïåðååõàëè â ÷ëåíû êëàññà
|
||||
// Объекты переехали в члены класса
|
||||
std::unique_ptr<boost::beast::websocket::stream<boost::beast::tcp_stream>> ws_;
|
||||
boost::beast::flat_buffer buffer_;
|
||||
|
||||
std::queue<std::string> messageQueue;
|
||||
std::mutex queueMutex; // Çàùèòà äëÿ messageQueue
|
||||
std::mutex queueMutex; // Защита для messageQueue
|
||||
|
||||
std::queue<std::shared_ptr<std::string>> writeQueue_;
|
||||
bool isWriting_ = false;
|
||||
std::mutex writeMutex_; // Îòäåëüíûé ìüþòåêñ äëÿ î÷åðåäè çàïèñè
|
||||
std::mutex writeMutex_; // Отдельный мьютекс для очереди записи
|
||||
|
||||
bool connected = false;
|
||||
int clientId = -1;
|
||||
|
||||
Reference in new issue
Block a user