同步和異步Socket的區別是,同步Socket會阻塞當前進程,而異步Socket則不會。
首先,一個最簡單的同步UDP收發程序實例。可以看到,發送調用Send()函數之后,開始調用Receive接收,這個時候程序會一直在這里等待,直到收到數據。
using System; using System.Net.Sockets; using System.Net; using System.Text; public class UdpClientTest { public static void Main() { UdpClient udpClient = new UdpClient(6000); //偵聽本地端口 IPEndPoint host = new IPEndPoint(IPAddress.Parse("192.168.191.1"),7000); //這里是目標主機和端口 Byte[] msg = new UTF8Encoding(true).GetBytes("Hee How are U?"); udpClient.Send(msg, msg.Length, host); IPEndPoint remoteHost = new IPEndPoint(IPAddress.Any,0); Byte[] receivedBytes = udpClient.Receive(ref remoteHost); string returnData = Encoding.ASCII.GetString(receivedBytes); Console.WriteLine("This is message you received is :"+returnData.ToString()); Console.WriteLine("This is was sent form : "+remoteHost.Address.ToString() + " port number " + remoteHost.Port.ToString()); udpClient.Close(); } }
下面是一個異步UDP的實例,
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net; using System.Net.Sockets; namespace Test { class UdpServer { public Socket serverSocket; public byte[] dataStream; public byte[] receivedBytes; public EndPoint epSender; // 關閉前一個窗口的回調函數 public delegate void OnDataReceived(); public event OnDataReceived onDataReceive; public UdpServer() { this.dataStream = new byte[10240]; } public void Open(int port) { this.serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint serverPoint = new IPEndPoint(IPAddress.Any, port); this.serverSocket.Bind(serverPoint); } public void Close() { this.serverSocket.Shutdown(SocketShutdown.Both); this.serverSocket.Close(); this.serverSocket.Shutdown(SocketShutdown.Both); this.serverSocket.Close(); } public void Listen() { try { IPEndPoint clientPoint = new IPEndPoint(IPAddress.Any, 0); this.epSender = (EndPoint)clientPoint; this.serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveData), epSender); } catch (Exception ex) { MessageBox.Show(ex.Message, "UDP連接創建失敗", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void ReceiveData(IAsyncResult asyncResult) { try { int recv_len = serverSocket.EndReceiveFrom(asyncResult, ref epSender); this.serverSocket.BeginReceiveFrom(this.dataStream, 0, this.dataStream.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveData), epSender); receivedBytes = new byte[recv_len]; Array.Copy(dataStream, 0, receivedBytes,0,recv_len); Console.WriteLine("got "+recv_len.ToString() + " Bytes"); Console.WriteLine("str is: "+ Encoding.ASCII.GetString(dataStream,0,recv_len)); onDataReceive(); } catch (Exception ex) { MessageBox.Show(ex.Message, "UDP接收異常", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } /* public void SendTo(IPEndPoint dstEndPoint, byte[] byteData,int length) { EndPoint dstHost = (EndPoint)dstEndPoint; // Begin sending the data to the remote device. this.serverSocket.BeginSendTo(byteData, 0, length, SocketFlags.None, dstHost, new AsyncCallback(SendCallback), this.serverSocket); }*/ private void SendTo(IPEndPoint dstEndPoint, string text) { byte[] byteData = Encoding.ASCII.GetBytes(text); EndPoint dstHost = (EndPoint)dstEndPoint; // Begin sending the data to the remote device. this.serverSocket.BeginSendTo(byteData, 0, byteData.Length, SocketFlags.None, dstHost, new AsyncCallback(SendCallback), this.serverSocket); } private void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket) ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); //handler.Shutdown(SocketShutdown.Both); //handler.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message, "UDP發送異常", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } public static void Main() { IPEndPoint dstPoint = new IPEndPoint(IPAddress.Parse("192.168.65.230"),7000);//發送到本地7000端口 UdpServer udpServer = new UdpServer(); udpServer.Open(6000); //本地偵聽6000端口 udpServer.Listen(); udpServer.SendTo(dstPoint, "Hello World!!!"); while(true) { } } } }