Fix: Calculate RTT exclude server side UI queue delay time
This commit is contained in:
@@ -1632,10 +1632,13 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
|||||||
void CKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength)
|
void CKernelManager::OnHeatbeatResponse(PBYTE szBuffer, ULONG ulLength)
|
||||||
{
|
{
|
||||||
if (ulLength > 8) {
|
if (ulLength > 8) {
|
||||||
uint64_t n = 0;
|
HeartbeatACK n = { 0 };
|
||||||
memcpy(&n, szBuffer + 1, sizeof(uint64_t));
|
const int size = sizeof(HeartbeatACK);
|
||||||
// 主控心跳 ACK 只回显时间戳(不含 ProcessingMs),近似纯网络 RTT
|
memcpy(&n, szBuffer + 1, ulLength > size ? size : HeartbeatACK_OldSize);
|
||||||
int64_t rtt_ms = (int64_t)GetUnixMs() - (int64_t)n;
|
int64_t total_rtt_ms = (int64_t)GetUnixMs() - (int64_t)n.Time;
|
||||||
|
int64_t rtt_ms = total_rtt_ms;
|
||||||
|
if (n.ProcessingMs > 0 && (int64_t)n.ProcessingMs < total_rtt_ms)
|
||||||
|
rtt_ms = total_rtt_ms - (int64_t)n.ProcessingMs;
|
||||||
m_nNetPing.update_from_sample((double)rtt_ms);
|
m_nNetPing.update_from_sample((double)rtt_ms);
|
||||||
// 试用版反代理:RTT 入采样窗口。
|
// 试用版反代理:RTT 入采样窗口。
|
||||||
// 启停由下方根据 m_settings 控制;非试用模式下 RecordSample 内部直接 return。
|
// 启停由下方根据 m_settings 控制;非试用模式下 RecordSample 内部直接 return。
|
||||||
|
|||||||
@@ -398,15 +398,18 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
|
|||||||
HeartbeatACK* ack = (HeartbeatACK*)(szBuffer + 1);
|
HeartbeatACK* ack = (HeartbeatACK*)(szBuffer + 1);
|
||||||
uint64_t now = GetUnixMs();
|
uint64_t now = GetUnixMs();
|
||||||
g_lastHeartbeatAckMs.store(now, std::memory_order_relaxed); // 喂应用层 ACK 看门狗
|
g_lastHeartbeatAckMs.store(now, std::memory_order_relaxed); // 喂应用层 ACK 看门狗
|
||||||
double rtt_ms = (double)(now - ack->Time);
|
int64_t total_rtt_ms = (int64_t)now - (int64_t)ack->Time;
|
||||||
g_rttEstimator.update_from_sample(rtt_ms);
|
int64_t rtt_ms = total_rtt_ms;
|
||||||
|
if (ack->ProcessingMs > 0 && (int64_t)ack->ProcessingMs < total_rtt_ms)
|
||||||
|
rtt_ms = total_rtt_ms - (int64_t)ack->ProcessingMs;
|
||||||
|
g_rttEstimator.update_from_sample((double)rtt_ms);
|
||||||
// 心跳节奏太密日志会刷屏;最多 60s 一行
|
// 心跳节奏太密日志会刷屏;最多 60s 一行
|
||||||
static time_t lastAckLog = 0;
|
static time_t lastAckLog = 0;
|
||||||
time_t now_s = time(nullptr);
|
time_t now_s = time(nullptr);
|
||||||
if (now_s - lastAckLog >= 60) {
|
if (now_s - lastAckLog >= 60) {
|
||||||
lastAckLog = now_s;
|
lastAckLog = now_s;
|
||||||
Mprintf("** [%p] Heartbeat ACK: RTT=%.1fms, SRTT=%.1fms ***\n",
|
Mprintf("** [%p] Heartbeat ACK: RTT=%.1fms, SRTT=%.1fms ***\n",
|
||||||
user, rtt_ms, g_rttEstimator.srtt * 1000);
|
user, (double)rtt_ms, g_rttEstimator.srtt * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (szBuffer[0] == CMD_MASTERSETTING) {
|
} else if (szBuffer[0] == CMD_MASTERSETTING) {
|
||||||
|
|||||||
@@ -750,14 +750,17 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
|
|||||||
if (ulLength >= 1 + sizeof(HeartbeatACK)) {
|
if (ulLength >= 1 + sizeof(HeartbeatACK)) {
|
||||||
HeartbeatACK* ack = (HeartbeatACK*)(szBuffer + 1);
|
HeartbeatACK* ack = (HeartbeatACK*)(szBuffer + 1);
|
||||||
uint64_t now = GetUnixMs();
|
uint64_t now = GetUnixMs();
|
||||||
double rtt_ms = (double)(now - ack->Time);
|
int64_t total_rtt_ms = (int64_t)now - (int64_t)ack->Time;
|
||||||
g_rttEstimator.update_from_sample(rtt_ms);
|
int64_t rtt_ms = total_rtt_ms;
|
||||||
|
if (ack->ProcessingMs > 0 && (int64_t)ack->ProcessingMs < total_rtt_ms)
|
||||||
|
rtt_ms = total_rtt_ms - (int64_t)ack->ProcessingMs;
|
||||||
|
g_rttEstimator.update_from_sample((double)rtt_ms);
|
||||||
// Log at most once per minute
|
// Log at most once per minute
|
||||||
static uint64_t lastLogTime = 0;
|
static uint64_t lastLogTime = 0;
|
||||||
if (now - lastLogTime >= 60000) {
|
if (now - lastLogTime >= 60000) {
|
||||||
lastLogTime = now;
|
lastLogTime = now;
|
||||||
Mprintf("** [%p] Heartbeat ACK: RTT=%.1fms, SRTT=%.1fms ***\n",
|
Mprintf("** [%p] Heartbeat ACK: RTT=%.1fms, SRTT=%.1fms ***\n",
|
||||||
user, rtt_ms, g_rttEstimator.srtt * 1000);
|
user, (double)rtt_ms, g_rttEstimator.srtt * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (szBuffer[0] == CMD_MASTERSETTING) {
|
} else if (szBuffer[0] == CMD_MASTERSETTING) {
|
||||||
|
|||||||
@@ -5715,6 +5715,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
|
|||||||
}
|
}
|
||||||
case TOKEN_HEARTBEAT:
|
case TOKEN_HEARTBEAT:
|
||||||
case 137: // 心跳【L】
|
case 137: // 心跳【L】
|
||||||
|
ContextObject->HeartbeatRecvMs.store(GetUnixMs(), std::memory_order_relaxed);
|
||||||
g_2015RemoteDlg->PostMessageA(WM_UPDATE_ACTIVEWND, 0, (LPARAM)ContextObject);
|
g_2015RemoteDlg->PostMessageA(WM_UPDATE_ACTIVEWND, 0, (LPARAM)ContextObject);
|
||||||
break;
|
break;
|
||||||
case TOKEN_SCREEN_PREVIEW_RSP: {
|
case TOKEN_SCREEN_PREVIEW_RSP: {
|
||||||
@@ -6488,10 +6489,9 @@ void CMy2015RemoteDlg::SendPendingRenewal(CONTEXT_OBJECT* ctx, const std::string
|
|||||||
|
|
||||||
void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx)
|
void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx)
|
||||||
{
|
{
|
||||||
// 记录本心跳的服务端处理开始时间,用于在 ACK 里回报 ProcessingMs。
|
// 用 IOCP 线程记录的收包时刻作为起点,排除 UI 消息队列等待时间,
|
||||||
// 客户端会用 (now - hb.Time) - ProcessingMs 算近似纯网络 RTT,喂给反代理检测,
|
// 使 ProcessingMs 仅反映真实服务端处理耗时。
|
||||||
// 避免授权链路里 VerifyClientAuth / HMAC / SignMessage 的耗时被误算为网络延迟。
|
const uint64_t t_start_ms = ctx->HeartbeatRecvMs.load(std::memory_order_relaxed);
|
||||||
const uint64_t t_start_ms = GetUnixMs();
|
|
||||||
|
|
||||||
auto clientID = ctx->GetClientID();
|
auto clientID = ctx->GetClientID();
|
||||||
auto host = FindHost(clientID);
|
auto host = FindHost(clientID);
|
||||||
|
|||||||
@@ -392,6 +392,10 @@ public:
|
|||||||
// 仅作为标记供后续命令处理 / 未来收紧策略使用。
|
// 仅作为标记供后续命令处理 / 未来收紧策略使用。
|
||||||
std::atomic<bool> m_bAuthenticated{false};
|
std::atomic<bool> m_bAuthenticated{false};
|
||||||
|
|
||||||
|
// 心跳包到达 IOCP 线程的时刻(ms),用于精确计算 ProcessingMs,
|
||||||
|
// 避免 UI 消息队列等待时间污染服务端耗时统计。
|
||||||
|
std::atomic<uint64_t> HeartbeatRecvMs{0};
|
||||||
|
|
||||||
// 预分配的解压缩缓冲区,避免频繁内存分配
|
// 预分配的解压缩缓冲区,避免频繁内存分配
|
||||||
PBYTE DecompressBuffer = nullptr;
|
PBYTE DecompressBuffer = nullptr;
|
||||||
ULONG DecompressBufferSize = 0;
|
ULONG DecompressBufferSize = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user