C# UDP+NAUDIO局域网声音组播传送与播放

C# UDP+NAUDIO局域网声音组播传送与播放

本实例通过采集麦克声音数据,利用udp组播方式在局域网中进行组播传送(类似在组内进行广播,udp广播、组播、单播请自行查阅相关资料),组内成员通过接收并播放到扬声器。
程序中引用了 Naudio 声音处理类库进行声音的采集与播放,可通过VS NuGet 查找并引用,关于声音处理相关技术请查阅相关文档。
防火墙要做好响应放行或直接关闭,否则数据无法接收和发送。另外可网管交换机也要做相应放行,否则也无法通讯。

运行效果:
C# UDP+NAUDIO局域网声音组播传送与播放_第1张图片
注意:两台pc要设置相同广播端口才可以。

using System;
using System.Windows.Forms;
using NAudio.Wave;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace Test
{
    public partial class FormNetSound : Form
    {
        private WaveIn mic;//音频输入,从mic采集,如果电脑硬件没有mic会报错
        private WaveOut speaker;//音频输出

        private BufferedWaveProvider _BWP;//接收声音缓冲
       
        private UdpClient2 receiver;//接收用
        private UdpClient2 multicaster;//组播用

        public FormNetSound()
        {
            InitializeComponent();

            lbl_mic.Visible = false;//声音输入设备打开标志
            lbl_speaker.Visible = false;//声音输出设备打开标志
         
        }
        /// 
        /// udp音频接收响应
        /// 
        /// pcm音频数据
        private void receive_sound(byte[] obj)
        { 
            _BWP.AddSamples(obj, 0, obj.Length);//添加到待播放缓存中
        }      
        /// 
        /// mic声音udp组播
        /// 
        /// 
        /// 
        private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
        {
            if (!lbl_mic.Visible) return;            

            multicaster.SendMessageByMulticast(e.Buffer,int.Parse(tb_dest_port.Text));           

        }

        private void btn_receive_Click(object sender, EventArgs e)
        {
            if (btn_receive.Text.Equals("静音"))
            {
                //接收udp组播数据用
                receiver = new UdpClient2(int.Parse(tb_dest_port.Text) , tb_dest_ip.Text);
                
                //生成默认声音播放对象
                speaker = new WaveOut();
                //设置声音格式
                WaveFormat wf = new WaveFormat(16000, 16, 1);

                //初始化待播放声音缓存对象
                _BWP = new BufferedWaveProvider(wf);

                //初始化播放设备
                speaker.Init(_BWP);

                if (receiver.recvMessageEvent == null)
                {
                    //绑定udpclient接收数据响应事件
                    receiver.recvMessageEvent += new Action<byte[]>(receive_sound);
                }

                
                receiver.Start();//开始接收数据
                btn_receive.Text = "打开";
                
                speaker.Play();//开始播放声音
                lbl_speaker.Visible = true;
                
            }else
            {
                btn_receive.Text = "静音";
                speaker.Stop();//停止播放声音
                receiver.CloseUdpCliend();//关闭接收           
                lbl_speaker.Visible = false;
            }
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            if (btn_send.Text.Equals("静音"))
            {
               //发送声音数据用
                multicaster = new UdpClient2(int.Parse(tb_local_port.Text) , tb_dest_ip.Text);

                mic = new WaveIn();//生成音频输入设备
                mic.WaveFormat = new WaveFormat(16000, 16 ,1); // 16bit,16KHz,Mono的录音格式
                
              
                //绑定声音输入处理事件
                mic.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);              

                multicaster.Start();//开始广播
                btn_send.Text = "打开";

                mic.StartRecording();//开始采集声音
                lbl_mic.Visible = true;
            }
            else
            {
                btn_send.Text = "静音";
                mic.StopRecording();//停止采集声音
                multicaster.CloseUdpCliend();//关闭组播
                lbl_mic.Visible = false;
            }
        }

      


    }
    
    public class UdpClient2
    {
        //接收数据事件
        public Action<byte[]> recvMessageEvent = null;
        //发送结果事件
        public Action<int> sendResultEvent = null;
        //本地监听端口
        public int localPort = 0;
        //组播地址
        public string MultiCastHost = "";

        

        private UdpClient udpClient = null;

        public UdpClient2(int localPort, string MultiCastHost)
        {
            if (localPort < 0 || localPort > 65535)
                throw new ArgumentOutOfRangeException("localPort is out of range");
            if (string.IsNullOrEmpty(MultiCastHost))
                throw new ArgumentNullException("message cant not null");

            this.localPort = localPort;
            this.MultiCastHost = MultiCastHost;
        }

        public void Start()
        {
            while (true)
            {
                try
                {
                    udpClient = new UdpClient(localPort);
                    udpClient.JoinMulticastGroup(IPAddress.Parse(MultiCastHost));
                    ReceiveMessage();
                    break;
                }
                catch (Exception)
                {
                    Thread.Sleep(100);
                }
            }
        }

        private async void ReceiveMessage()
        {
            while (true)
            {
                if (udpClient == null)
                    return;

                try
                {
                    
                    UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
                    byte[] message = udpReceiveResult.Buffer;
                    if (recvMessageEvent != null)
                        recvMessageEvent(message);
                }
                catch (Exception ex)
                {
                }
            }
        }

        public async void SendMessageByMulticast(byte[] message,int destport)
        {
           
            if (udpClient == null) return;
            

            byte[] buffer = message;
            int len = 0;
            for (int i = 0; i < 1; i++)
            {
                try
                {
                    len = await udpClient.SendAsync(buffer, buffer.Length, new IPEndPoint(IPAddress.Parse(MultiCastHost), destport));
                }
                catch (Exception)
                {
                    len = 0;
                }

                if (len <= 0)
                    Thread.Sleep(100);
                else
                    break;
            }

            if (sendResultEvent != null)
                sendResultEvent(len);
        }

        public void CloseUdpCliend()
        {
            if (udpClient == null)
                throw new ArgumentNullException("udpClient cant not null");

            try
            {
                udpClient.Client.Shutdown(SocketShutdown.Both);
            }
            catch (Exception)
            {
            }
            udpClient.Close();
            udpClient = null;
        }
    }
}

你可能感兴趣的:(C#,UDP,组播)