【m】优化socket代码
This commit is contained in:
243
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs
vendored
Normal file
243
Packages/com.unity.renderstreaming@3.1.0-exp.9/Runtime/Scripts/HostConnection.cs
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.RenderStreaming
|
||||
{
|
||||
/// <summary>
|
||||
/// Host模式的连接处理器
|
||||
/// 适用于私有模式下Unity作为Host(第一个加入房间的客户端)
|
||||
/// 支持多个Participant连接,每个Participant拥有独立的PeerConnection
|
||||
///
|
||||
/// 工作原理:
|
||||
/// - Host通过CreateConnection(connectionId)创建房间连接
|
||||
/// - 当Participant加入时,服务器发送participant-joined通知
|
||||
/// - WebSocketSignaling将participantId作为内部connectionId使用,
|
||||
/// 因此每个Participant会自动创建独立的PeerConnection
|
||||
/// - 当收到Participant的offer时,自动添加Stream并发送answer
|
||||
/// - 当Participant离开时,自动清理对应的连接资源
|
||||
/// </summary>
|
||||
[AddComponentMenu("Render Streaming/Host Connection")]
|
||||
public class HostConnection : SignalingHandlerBase,
|
||||
IOfferHandler, IAddChannelHandler, IDisconnectHandler, IDeletedConnectionHandler,
|
||||
IAddReceiverHandler, IParticipantJoinedHandler, IParticipantLeftHandler,
|
||||
ICallRequestHandler, IMessageHandler
|
||||
{
|
||||
[SerializeField] private List<Component> streams = new List<Component>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前连接的所有Participant的participantId列表
|
||||
/// </summary>
|
||||
private List<string> participantIds = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 房间的connectionId(Host创建连接时使用的ID)
|
||||
/// </summary>
|
||||
private string roomConnectionId;
|
||||
|
||||
public override IEnumerable<Component> Streams => streams;
|
||||
|
||||
public void AddComponent(Component component)
|
||||
{
|
||||
streams.Add(component);
|
||||
}
|
||||
|
||||
public void RemoveComponent(Component component)
|
||||
{
|
||||
streams.Remove(component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Host连接(即创建房间)
|
||||
/// Unity作为第一个连接的客户端,服务器会分配host角色(polite=false)
|
||||
/// </summary>
|
||||
/// <param name="connectionId">房间ID</param>
|
||||
public override void CreateConnection(string connectionId)
|
||||
{
|
||||
roomConnectionId = connectionId;
|
||||
base.CreateConnection(connectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除Host连接(关闭房间)
|
||||
/// Host离开时,服务器会自动断开所有Participant
|
||||
/// </summary>
|
||||
public override void DeleteConnection(string connectionId)
|
||||
{
|
||||
// 清理所有Participant连接
|
||||
foreach (var participantId in participantIds.ToList())
|
||||
{
|
||||
DisconnectParticipant(participantId);
|
||||
}
|
||||
participantIds.Clear();
|
||||
|
||||
if (connectionId == roomConnectionId)
|
||||
{
|
||||
base.DeleteConnection(connectionId);
|
||||
roomConnectionId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.DeleteConnection(connectionId);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDeletedConnection(SignalingEventData eventData)
|
||||
{
|
||||
Disconnect(eventData.connectionId);
|
||||
}
|
||||
|
||||
public void OnDisconnect(SignalingEventData eventData)
|
||||
{
|
||||
Disconnect(eventData.connectionId);
|
||||
}
|
||||
|
||||
private void Disconnect(string connectionId)
|
||||
{
|
||||
if (!participantIds.Contains(connectionId) && connectionId != roomConnectionId)
|
||||
return;
|
||||
|
||||
participantIds.Remove(connectionId);
|
||||
|
||||
foreach (var sender in streams.OfType<IStreamSender>())
|
||||
{
|
||||
RemoveSender(connectionId, sender);
|
||||
}
|
||||
foreach (var receiver in streams.OfType<IStreamReceiver>())
|
||||
{
|
||||
RemoveReceiver(connectionId, receiver);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == connectionId))
|
||||
{
|
||||
RemoveChannel(connectionId, channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开指定Participant的连接资源
|
||||
/// </summary>
|
||||
private void DisconnectParticipant(string participantId)
|
||||
{
|
||||
foreach (var sender in streams.OfType<IStreamSender>())
|
||||
{
|
||||
RemoveSender(participantId, sender);
|
||||
}
|
||||
foreach (var receiver in streams.OfType<IStreamReceiver>())
|
||||
{
|
||||
RemoveReceiver(participantId, receiver);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.ConnectionId == participantId))
|
||||
{
|
||||
RemoveChannel(participantId, channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到Participant的offer时触发
|
||||
/// WebSocketSignaling已经将participantId作为内部connectionId
|
||||
/// 所以每个Participant的offer会自动创建独立的PeerConnection
|
||||
/// </summary>
|
||||
public void OnOffer(SignalingEventData data)
|
||||
{
|
||||
// 记录新的Participant连接
|
||||
if (!participantIds.Contains(data.connectionId))
|
||||
{
|
||||
participantIds.Add(data.connectionId);
|
||||
Debug.Log($"[HostConnection] Participant offer received: {data.connectionId}");
|
||||
}
|
||||
|
||||
// 为该Participant添加所有Stream
|
||||
foreach (var source in streams.OfType<IStreamSender>())
|
||||
{
|
||||
AddSender(data.connectionId, source);
|
||||
}
|
||||
foreach (var channel in streams.OfType<IDataChannel>().Where(c => c.IsLocal))
|
||||
{
|
||||
AddChannel(data.connectionId, channel);
|
||||
}
|
||||
|
||||
// 发送answer给该Participant
|
||||
SendAnswer(data.connectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到远程Track时触发
|
||||
/// </summary>
|
||||
public void OnAddReceiver(SignalingEventData data)
|
||||
{
|
||||
var track = data.transceiver.Receiver.Track;
|
||||
IStreamReceiver receiver = GetReceiver(track.Kind);
|
||||
SetReceiver(data.connectionId, receiver, data.transceiver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到远程DataChannel时触发
|
||||
/// </summary>
|
||||
public void OnAddChannel(SignalingEventData data)
|
||||
{
|
||||
var channel = streams.OfType<IDataChannel>().
|
||||
FirstOrDefault(r => !r.IsConnected && !r.IsLocal);
|
||||
channel?.SetChannel(data.connectionId, data.channel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新Participant加入房间通知
|
||||
/// 在私有模式下,服务器会通知Host有新的Participant加入
|
||||
/// 此时不做额外处理,等收到Participant的offer时再建立连接
|
||||
/// </summary>
|
||||
public void OnParticipantJoined(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Participant joined: connectionId={eventData.connectionId}, participantId={eventData.participantId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Participant离开房间通知
|
||||
/// 清理该Participant的连接资源
|
||||
/// </summary>
|
||||
public void OnParticipantLeft(SignalingEventData eventData)
|
||||
{
|
||||
string participantId = eventData.participantId;
|
||||
if (!string.IsNullOrEmpty(participantId))
|
||||
{
|
||||
Debug.Log($"[HostConnection] Participant left: connectionId={eventData.connectionId}, participantId={participantId}");
|
||||
DisconnectParticipant(participantId);
|
||||
participantIds.Remove(participantId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到呼叫请求
|
||||
/// </summary>
|
||||
public void OnCallRequest(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Call request from: {eventData.connectionId}, data: {eventData.message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收到自定义消息
|
||||
/// </summary>
|
||||
public void OnMessage(SignalingEventData eventData)
|
||||
{
|
||||
Debug.Log($"[HostConnection] Message from: {eventData.connectionId}, participantId: {eventData.participantId}, message: {eventData.message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前连接的Participant数量
|
||||
/// </summary>
|
||||
public int ParticipantCount => participantIds.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有Participant的ID列表
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> ParticipantIds => participantIds.AsReadOnly();
|
||||
|
||||
IStreamReceiver GetReceiver(WebRTC.TrackKind kind)
|
||||
{
|
||||
if (kind == WebRTC.TrackKind.Audio)
|
||||
return streams.OfType<AudioStreamReceiver>().FirstOrDefault();
|
||||
if (kind == WebRTC.TrackKind.Video)
|
||||
return streams.OfType<VideoStreamReceiver>().FirstOrDefault();
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user