// using System; // using Unity.RenderStreaming.Signaling; // using UnityEngine; // using Unity.WebRTC; // // namespace Unity.RenderStreaming.Samples // { // /// // /// 心跳接收通道 - 继承 DataChannelBase(对应博客中的 ReceiveChannel) // /// 接收服务端发送的 Ping,回复 Pong // /// // class HeartbeatReceiveChannel : DataChannelBase // { // // 消息类型(必须与服务端保持一致) // private const int MSG_TYPE_PING = 1; // private const int MSG_TYPE_PONG = 2; // // // 统计信息 // public long LastRtt { get; private set; } // public float AverageRtt { get; private set; } // public int ReceivedPingCount { get; private set; } // // // 事件 // public event Action OnPingReceived; // 参数:RTT // public event Action OnTimeoutWarning; // 超时警告 // // private System.Collections.Generic.Queue _latencyHistory = new System.Collections.Generic.Queue(10); // // [Serializable] // private class HeartbeatMessage // { // public int type; // 1=ping, 2=pong // public long timestamp; // 服务端发送时间戳 // public int seq; // 序列号 // } // // // /// // /// 重写 OnMessage - 当收到数据时自动调用(对应博客中的 ReceiveChannel 实现) // /// // protected override void OnMessage(byte[] bytes) // { // try // { // string json = System.Text.Encoding.UTF8.GetString(bytes); // var msg = JsonUtility.FromJson(json); // // if (msg.type == MSG_TYPE_PING) // { // HandlePing(msg); // } // } // catch (Exception e) // { // Debug.LogError($"[心跳接收通道] 消息解析失败: {e.Message}"); // } // } // // /// // /// 处理 Ping 消息并回复 Pong // /// // private void HandlePing(HeartbeatMessage ping) // { // long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); // long latency = now - ping.timestamp; // // ReceivedPingCount++; // LastRtt = latency; // // // 更新平均延迟 // _latencyHistory.Enqueue(latency); // if (_latencyHistory.Count > 10) // _latencyHistory.Dequeue(); // // long sum = 0; // foreach (var lat in _latencyHistory) // sum += lat; // AverageRtt = sum / (float)_latencyHistory.Count; // // Debug.Log($"[心跳接收通道] 收到 Ping #{ping.seq}, 延迟: {latency}ms, 平均: {AverageRtt:F1}ms"); // // // 立即回复 Pong(关键:回传原始时间戳,方便服务端计算 RTT) // SendPong(ping.timestamp, ping.seq); // // // 触发事件 // OnPingReceived?.Invoke(latency); // } // // /// // /// 发送 Pong 响应 // /// // private void SendPong(long originalTimestamp, int seq) // { // if (Channel == null || Channel.ReadyState != RTCDataChannelState.Open) // { // Debug.LogWarning("[心跳接收通道] 通道未打开,无法发送 Pong"); // return; // } // // var pong = new HeartbeatMessage // { // type = MSG_TYPE_PONG, // timestamp = originalTimestamp, // 回传服务端的时间戳 // seq = seq // }; // // string json = JsonUtility.ToJson(pong); // byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json); // // Channel.Send(bytes); // Debug.Log($"[心跳接收通道] 发送 Pong #{seq}"); // } // // /// // /// 获取当前连接状态 // /// // public bool IsConnected => Channel != null && Channel.ReadyState == RTCDataChannelState.Open; // } // }