正如对您问题的评论所说,通常首选 UDP 或其他流协议。但是随着 WCF 提供更多的抽象,做这样的事情会更容易。话虽如此,我已经使用 WCF 在我们以前的一个软件(该软件被 LAN 中的多个客户端使用)实现了语音聊天功能netTcpBinding
,并且运行良好(我在 LAN 中使用 5 个客户端对其进行了测试),你可以并不是真的觉得 WCF 阻碍了架构。随着支持 UDP 传输的 WCF 4.5 的发布,这将变得有趣。
对于这样的事情,您应该真正了解 WCF 中双工通信的要点。我这样做的方式是,我的服务上有一个SendVoice()
操作合同,每次客户端将他们的音频流发送到服务时,该SendVoice()
方法将遍历订阅者列表(连接的客户端)并SendVoiceCallback()
在每个客户端上调用。你可以从这样的事情开始:
public void SendVoice(byte[] audio)
{
//Keep a list of connected clients in a dictionary called subscribers
//lock your subscribers list so that it's not modified when you're in the middle of sending the stream
lock (subscribers)
{
//send the received voice stream to each client
foreach (var _subscriber in subscribers)
{
if (OperationContext.Current.GetCallbackChannel<IVoiceChatCallback>() == subscriber.Key)
{
//if the person who sent the video is the current subscriber then don't send the video to THAT subscriber
continue;
}
try
{
//Send the received stream to the client asynchronously
_subscriber.Key.BeginOnVoiceSendCallback(audio, onNotifyCompletedVoiceSend, _subscriber.Key);
}
catch (Exception)
{
//fault handling
}
}
}
}
然后,您的客户会定期调用上述方法,在我的实现中,我将其设置为每 250 毫秒,它运行得非常好(显然有一个小的延迟)。
在上面的代码IVoiceChatCallback
中是回调合约。回调使服务能够在客户端上调用某些操作,因此例如客户端的行为就像服务器一样。异步服务调用意味着您SendVoice()
将异步发布音频到每个客户端,而不是在发送新流之前等待前一个流到达客户端。
上面的代码只是您入门的一个想法。您应该向服务中添加一些故障处理代码,以检查客户端何时断开连接并将它们从您的订阅者字典中删除。同样,您应该熟悉 WCF 中的异步操作调用以及回调。此外,如果您希望在 LAN 中使用它,那么netTcpBinding
就是要走的路,您应该配置您的服务以优化其吞吐量和并发性。在 Internet 上,您需要使用支持双工的 Http 绑定。