首页 / 软件开发 / WCF / WPF+WCF一步一步打造音频聊天室(三):语音聊天
WPF+WCF一步一步打造音频聊天室(三):语音聊天2012-05-20 博客园 朱祁林前一篇文章中实现了文字聊天和共享白板的功能,这篇文章中,我将在前一篇文章的基础上实现语音聊天的功能。语音聊天要比文字聊 天和共享白板难度要大一点。实现的大概的流程为:1、一个聊天室成员向另外一个成员发起语音聊天请求2、这个请求将被送至WCF服务端,WCF的双工通知被邀请人。3、被邀请人接到通知,他可以选择接受或者拒绝语音聊天的请求。4、如果拒绝,将通知请求者拒绝语音聊天5、如果同意,邀请者和被邀请者的客户端将进行语音聊天,此时客户端会开启一个播放声音和接受声音的线程。这里用到了一个开源 的wave类库,在http://www.lumisoft.ee/lswww/download/downloads/Examples/可以下载。声音的通信使用到了UDPClient 类。这个类使 用 UDP 与网络服务通讯。UDP 的优点是简单易用,并且能够同时向多个地址广播消息。UdpClient 类提供了一些简单的方法,用于在阻止 同步模式下发送和接收无连接 UDP 数据报。因为 UDP 是无连接传输协议,所以不需要在发送和接收数据前建立远程主机连接。但您可以 选择使用下面两种方法之一来建立默认远程主机:*使用远程主机名和端口号作为参数创建 UdpClient 类的实例。*创建 UdpClient 类的实例,然后调用 Connect 方法。可以使用在UdpClient 中提供的任何一种发送方法将数据发送到远程设备。使用 Receive 方法可以从远程主机接收数据。这篇文章使用了Receive 方法从客户端接受数据。然后通过WCF中存储的IP地址,通过Send方法将其发送给客户端。下面我将在前一篇文章的基础上实现这个语音聊天的功能。首先在客户端添加声音管理的类CallManager,这个类使用到了开源的wave 类库,代码如下:public class CallManager
{
private WaveIn _waveIn;
private WaveOut _waveOut;
private IPEndPoint _serverEndPoint;
private Thread _playSound;
private UdpClient _socket;
public CallManager(IPEndPoint serverEndpoint)
{
_serverEndPoint = serverEndpoint;
}
public void Start()
{
if (_waveIn != null || _waveOut != null)
{
throw new Exception("Call is allready started");
}
int waveInDevice = (Int32)Application.UserAppDataRegistry.GetValue("WaveIn", 0);
int waveOutDevice = (Int32)Application.UserAppDataRegistry.GetValue("WaveOut", 0);
_socket = new UdpClient(0); // opens a random available port on all interfaces
_waveIn = new WaveIn(WaveIn.Devices[waveInDevice], 8000, 16, 1, 400);
_waveIn.BufferFull += new BufferFullHandler(_waveIn_BufferFull);
_waveIn.Start();
_waveOut = new WaveOut(WaveOut.Devices[waveOutDevice], 8000, 16, 1);
_playSound = new Thread(new ThreadStart(playSound));
_playSound.IsBackground = true;
_playSound.Start();
}
private void playSound()
{
try
{
while (true)
{
lock (_socket)
{
if (_socket.Available != 0)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] received = _socket.Receive(ref endpoint);
// todo: add codec
_waveOut.Play(received, 0, received.Length);
}
}
Thread.Sleep(1);
}
}
catch (ThreadAbortException)
{
}
catch
{
this.Stop();
}
}
void _waveIn_BufferFull(byte[] buffer)
{
lock (_socket)
{
//todo: add codec
_socket.Send(buffer, buffer.Length, _serverEndPoint);
}
}
public void Stop()
{
if (_waveIn != null)
{
_waveIn.Dispose();
}
if (_waveOut != null)
{
_waveOut.Dispose();
}
if (_playSound.IsAlive)
{
_playSound.Abort();
}
if (_socket != null)
{
_socket.Close();
_socket = null;
}
}
}