C#基于UDP实现的P2P语音聊天工具

开发 后端 开发工具
这篇文章主要是一个应用,使用udp传送语音和文本等信息。在这个系统中没有服务端和客户端,相互通讯都是直接相互联系的。能够很好的实现效果。

这篇文章主要是一个应用,使用udp传送语音和文本等信息。在这个系统中没有服务端和客户端,相互通讯都是直接相互联系的。能够很好的实现效果。

语音获取

要想发送语音信息,首先得获取语音,这里有几种方法,一种是使用DirectX的DirectXsound来录音,我为了简便使用一个开源的插件NAudio来实现语音录取。 在项目中引用NAudio.dll

 

//------------------录音相关----------------------------- 
        private IWaveIn waveIn; 
        private WaveFileWriter writer; 
 
        private void LoadWasapiDevicesCombo() 
        { 
            var deviceEnum = new MMDeviceEnumerator(); 
            var devices = deviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToList(); 
            comboBox1.DataSource = devices; 
            comboBox1.DisplayMember = "FriendlyName"
        } 
        private void CreateWaveInDevice() 
        { 
 
            waveIn = new WaveIn(); 
            waveIn.WaveFormat = new WaveFormat(80001); 
            waveIn.DataAvailable += OnDataAvailable; 
            waveIn.RecordingStopped += OnRecordingStopped; 
        } 
        void OnDataAvailable(object sender, WaveInEventArgs e) 
        { 
            if (this.InvokeRequired) 
            { 
                this.BeginInvoke(new EventHandler<WaveInEventArgs>(OnDataAvailable), sender, e); 
            } 
            else 
            { 
                writer.Write(e.Buffer, 0, e.BytesRecorded); 
                int secondsRecorded = (int)(writer.Length / writer.WaveFormat.AverageBytesPerSecond); 
                if (secondsRecorded >= 10)//***10s 
                { 
                    StopRecord(); 
                } 
                else 
                { 
                    l_sound.Text = secondsRecorded + " s"
                } 
            } 
        } 
        void OnRecordingStopped(object sender, StoppedEventArgs e) 
        { 
            if (InvokeRequired) 
            { 
                BeginInvoke(new EventHandler<StoppedEventArgs>(OnRecordingStopped), sender, e); 
            } 
            else 
            { 
                FinalizeWaveFile(); 
            } 
        } 
        void StopRecord() 
        { 
            AllChangeBtn(btn_luyin, true); 
            AllChangeBtn(btn_stop, false); 
            AllChangeBtn(btn_sendsound, true); 
            AllChangeBtn(btn_play, true); 
 
            //btn_luyin.Enabled = true; 
            //btn_stop.Enabled = false; 
            //btn_sendsound.Enabled = true; 
            //btn_play.Enabled = true; 
            if (waveIn != null
                waveIn.StopRecording(); 
            //Cleanup(); 
        } 
  private void Cleanup() 
        { 
            if (waveIn != null
            { 
                waveIn.Dispose(); 
                waveIn = null
            } 
            FinalizeWaveFile(); 
        } 
        private void FinalizeWaveFile() 
        { 
            if (writer != null
            { 
                writer.Dispose(); 
                writer = null
            } 
        } 
   //开始录音 
        private void btn_luyin_Click(object sender, EventArgs e) 
        { 
            btn_stop.Enabled = true
            btn_luyin.Enabled = false
            if (waveIn == null
            { 
                CreateWaveInDevice(); 
            } 
            if (File.Exists(soundfile)) 
            { 
                File.Delete(soundfile); 
            } 
 
            writer = new WaveFileWriter(soundfile, waveIn.WaveFormat); 
            waveIn.StartRecording(); 
        } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.

上面的代码实现了录音,并且写入文件p2psound_A.wav

 

C#基于UDP实现的P2P语音聊天工具

#p#

语音发送

获取到语音后我们要把语音发送出去

当我们录好音后点击发送,这部分相关代码是

 

MsgTranslator tran = null
ublic Form1() 
       { 
           InitializeComponent(); 
           LoadWasapiDevicesCombo();//显示音频设备 
 
           Config cfg = SeiClient.GetDefaultConfig(); 
           cfg.Port = 7777
           UDPThread udp = new UDPThread(cfg); 
           tran = new MsgTranslator(udp, cfg); 
           tran.MessageReceived += tran_MessageReceived; 
           tran.Debuged += new EventHandler<DebugEventArgs>(tran_Debuged); 
       } 
 private void btn_sendsound_Click(object sender, EventArgs e) 
       { 
           if (t_ip.Text == ""
           { 
               MessageBox.Show("请输入ip"); 
               return
           } 
           if (t_port.Text == ""
           { 
               MessageBox.Show("请输入端口号"); 
               return
           } 
           string ip = t_ip.Text; 
           int port = int.Parse(t_port.Text); 
           string nick = t_nick.Text; 
           string msg = "语音消息"
 
           IPEndPoint remote = new IPEndPoint(IPAddress.Parse(ip), port); 
           Msg m = new Msg(remote, "zz", nick, Commands.SendMsg, msg, "Come From A"); 
           m.IsRequireReceive = true
           m.ExtendMessageBytes = FileContent(soundfile); 
           m.PackageNo = Msg.GetRandomNumber(); 
           m.Type = Consts.MESSAGE_BINARY; 
           tran.Send(m); 
       } 
 private byte[] FileContent(string fileName) 
       { 
           FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
           try 
           { 
               byte[] buffur = new byte[fs.Length]; 
               fs.Read(buffur, 0, (int)fs.Length); 
 
               return buffur; 
           } 
           catch (Exception ex) 
           { 
               return null
           } 
           finally 
           { 
               if (fs != null
               { 
 
                   //关闭资源 
                   fs.Close(); 
               } 
           } 
       } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

如此一来我们就把产生的语音文件发送出去了

语音的接收与播放

其实语音的接收和文本消息的接收没有什么不同,只不过语音发送的时候是以二进制发送的,因此我们在收到语音后 就应该写入到一个文件里面去,接收完成后,播放这段语音就行了。

下面这段代码主要是把收到的数据保存到文件中去,这个函数式我的NetFrame里收到消息时所触发的事件,在文章前面提过的那篇文章里

 

void tran_MessageReceived(object sender, MessageEventArgs e) 
        { 
            Msg msg = e.msg; 
 
            if (msg.Type == Consts.MESSAGE_BINARY) 
            { 
                string m = msg.Type + "->" + msg.UserName + "发来二进制消息!"
                AddServerMessage(m); 
                if (File.Exists(recive_soundfile)) 
                { 
                    File.Delete(recive_soundfile); 
                } 
                FileStream fs = new FileStream(recive_soundfile, FileMode.Create, FileAccess.Write); 
                fs.Write(msg.ExtendMessageBytes, 0, msg.ExtendMessageBytes.Length); 
                fs.Close(); 
                //play_sound(recive_soundfile); 
                ChangeBtn(true); 
 
            } 
            else 
            { 
                string m = msg.Type + "->" + msg.UserName + "说:" + msg.NormalMsg; 
                AddServerMessage(m); 
            } 
        } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

收到语音消息后,我们要进行播放,播放时仍然用刚才那个插件播放

 

//--------播放部分---------- 
        private IWavePlayer wavePlayer; 
        private WaveStream reader; 
 
        public void play_sound(string filename) 
        { 
            if (wavePlayer != null
            { 
                wavePlayer.Dispose(); 
                wavePlayer = null
            } 
            if (reader != null
            { 
                reader.Dispose(); 
            } 
            reader = new MediaFoundationReader(filename, new MediaFoundationReader.MediaFoundationReaderSettings() { SingleReaderObject = true }); 
 
            if (wavePlayer == null
            { 
 
                wavePlayer = new WaveOut(); 
                wavePlayer.PlaybackStopped += WavePlayerOnPlaybackStopped; 
                wavePlayer.Init(reader); 
            } 
            wavePlayer.Play(); 
        } 
        private void WavePlayerOnPlaybackStopped(object sender, StoppedEventArgs stoppedEventArgs) 
        { 
            if (stoppedEventArgs.Exception != null
            { 
                MessageBox.Show(stoppedEventArgs.Exception.Message); 
            } 
            if (wavePlayer != null
            { 
                wavePlayer.Stop(); 
            } 
            btn_luyin.Enabled = true
        }private void btn_play_Click(object sender, EventArgs e) 
        { 
            btn_luyin.Enabled = false
            play_sound(soundfile); 
        } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.

 

C#基于UDP实现的P2P语音聊天工具

C#基于UDP实现的P2P语音聊天工具

在上面演示了接收和发送一段语音消息的界面

技术总结

主要用到的技术就是UDP和NAudio的录音和播放功能

其中用到的UDP传输类我放在了github上面 地址在我的博客左边的个人介绍里有地址  项目地址 https://github.com/zhujunxxxxx/ZZNetFrame

希望这篇文章能够提供一个思路。

责任编辑:王雪燕 来源: 码农网
相关推荐

2010-07-08 14:35:32

UDP协议

2012-09-25 13:47:43

C#网络协议P2P

2017-05-10 11:10:15

LinuxUbuntuDiscord

2020-03-05 20:30:15

Syncthing文件同步工具开源

2024-08-06 14:03:35

2010-07-13 08:19:10

Linux聊天工具

2021-09-02 19:45:21

P2P互联网加速

2012-12-10 09:46:21

P2P云存储Symform

2009-05-18 09:11:00

IPTV融合宽带

2019-03-07 14:45:07

聊天工具富文本输入框前端

2022-02-12 12:18:59

Delta Chat聊天应用开源

2011-12-21 17:39:03

imo即时通讯

2011-06-27 10:58:31

Qt 局域网 聊天

2011-11-30 10:48:21

2010-03-22 15:27:40

云计算

2010-07-13 14:41:14

2022-07-19 16:59:04

流媒体传输IPC物联网

2015-12-01 15:33:21

P2P端口映射工具dog-tunnel狗洞

2010-03-10 10:51:30

2010-07-07 10:31:45

点赞
收藏

51CTO技术栈公众号