C#裡面Socket有非同步和同步之分,可參考:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/socket-code-examples進行學習。網路上很多有關DirectSound的Socket聲音採集樣本,不過都是單獨的一個工具類(如:DirectSoundCapture),花了點時間實現了Socket的調用,順便總結分享一下。下圖為測試樣本:
Socket用戶端
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading.Tasks;/// <summary>/// 參考:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/socket-code-examples/// </summary>namespace DirectsoundTest{ class SocketClient { /// <summary> /// 啟動用戶端socket串連 /// </summary> public static void StartClient(string data) { // Data buffer for incoming data. byte[] bytes = new byte[1024]; // Connect to a remote device. try { // Establish the remote endpoint for the socket. // This example uses port 11000 on the local computer. IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket sender = new Socket(ipAddress.AddressFamily,SocketType.Stream, ProtocolType.Tcp); // Connect the socket to the remote endpoint. Catch any errors. try { sender.Connect(remoteEP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); // Encode the data string into a byte array. byte[] msg = Encoding.UTF8.GetBytes(data+"<EOF>"); // Send the data through the socket. int bytesSent = sender.Send(msg); // Receive the response from the remote device. int bytesRec = sender.Receive(bytes); Console.WriteLine("Echoed test = {0}", Encoding.UTF8.GetString(bytes, 0, bytesRec)); // Release the socket. sender.Shutdown(SocketShutdown.Both); sender.Close(); } catch (ArgumentNullException ane) { Console.WriteLine("ArgumentNullException : {0}", ane.ToString()); } catch (SocketException se) { Console.WriteLine("SocketException : {0}", se.ToString()); } catch (Exception e) { Console.WriteLine("Unexpected exception : {0}", e.ToString()); } } catch (Exception e) { Console.WriteLine(e.ToString()); } } }}
Socket服務端
using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading.Tasks;/// <summary>/// 參考:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/socket-code-examples/// </summary>namespace DirectsoundTest{ class SocketServer { // Incoming data from the client. public static string data = null; /// <summary> /// 啟動服務端socket監聽 /// </summary> public static void StartListening() { // Data buffer for incoming data. byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket. // Dns.GetHostName returns the name of the // host running the application. IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket listener = new Socket(ipAddress.AddressFamily,SocketType.Stream, ProtocolType.Tcp); // Bind the socket to the local endpoint and // listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(10); // Start listening for connections. while (true) { Console.WriteLine("Waiting for a connection..."); // Program is suspended while waiting for an incoming connection. Socket handler = listener.Accept(); data = null; // An incoming connection needs to be processed. while (true) { bytes = new byte[1024]; int bytesRec = handler.Receive(bytes); data += Encoding.UTF8.GetString(bytes, 0, bytesRec); if (data.IndexOf("<EOF>") > -1) { break; } } // Show the data on the console. Console.WriteLine("Text received : {0}", data); // Echo the data back to the client. byte[] msg = Encoding.UTF8.GetBytes(data); handler.Send(msg); handler.Shutdown(SocketShutdown.Both); handler.Close(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } }}
表單&委託傳值
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace DirectsoundTest{ public partial class FrmSocket : Form { public FrmSocket() { InitializeComponent(); } /// <summary> /// 啟動服務端socket串連 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnBindSocketServer_Click(object sender, EventArgs e) { btnBindSocketServer.Enabled = false; Thread thread = new Thread(() => { SocketServer.StartListening(); }); thread.IsBackground = true; thread.Start(); } // 委託設定值 delegate void setDataToListView(string data); private void SetListViewData(string data) { if (this.listViewData.InvokeRequired) { setDataToListView stcb = new setDataToListView(SetListViewData); this.Invoke(stcb, new object[] { data }); } else { this.listViewData.Items.Add(data); } } /// <summary> /// 用戶端發送socket串連資料 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSocketClient_Click(object sender, EventArgs e) { // 發送UTF8文字 byte[] buffer = Encoding.UTF8.GetBytes(this.textBox.Text.ToString()); string data = Encoding.UTF8.GetString(buffer); Thread thread = new Thread(() => { SocketClient.StartClient(data); SetListViewData(data);//委託設定控制項的值 }); thread.IsBackground = true; thread.Start(); } /// <summary> /// 開啟服務端 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void toolStripMenuItemServer_Click(object sender, EventArgs e) { if (!Setting.SERVER_BINDED) { FrmServer frmServer = new FrmServer(); frmServer.Show(); Setting.SERVER_BINDED = true; } else { MessageBox.Show("服務端登入"); } } /// <summary> /// 開啟用戶端 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void toolStripMenuItemClient_Click(object sender, EventArgs e) { FrmClient frmClient = new FrmClient(); frmClient.Show(); } }}
委託寫法-實現跨線程修改ListView控制項值:
// 委託設定值 delegate void setDataToListView(string data); private void SetListViewData(string data) { if (this.listViewData.InvokeRequired) { setDataToListView stcb = new setDataToListView(SetListViewData); this.Invoke(stcb, new object[] { data }); } else { this.listViewData.Items.Add(data); } }
DirectSound錄音測試源碼 Socket例子和DirectSound錄音代碼都在Github上可以找到。
Github地址:https://github.com/BoonyaCSharp-ASP/DirectSoundTest