傳統同步 Accept() 會阻塞主執行緒,導致應用程式無法處理其他工作(如 UI 回應、其他連線)。非同步模式將「等待連線」交給作業系統與執行緒池,主執行緒得以自由執行其他邏輯。
| Begin 方法 | End 方法 | 功能 |
|---|---|---|
| BeginAccept | EndAccept | 非同步接受連入連線 |
| BeginConnect | EndConnect | 非同步連線至遠端 |
| BeginDisconnect | EndDisconnect | 非同步斷開連線 |
| BeginReceive | EndReceive | 非同步接收資料 |
| BeginReceiveFrom | EndReceiveFrom | 非同步從指定裝置接收 (UDP) |
| BeginSend | EndSend | 非同步發送資料 |
| BeginSendFile | EndSendFile | 非同步發送檔案 |
| BeginSendTo | EndSendTo | 非同步發送至特定遠端 (UDP) |
所有方法皆為成對出現,核心機制:在 Begin 方法註冊回呼,事件發生時執行回呼,回呼中呼叫對應 End 方法取得結果。
public IAsyncResult BeginAccept(AsyncCallback callback, object state);
callback:連線建立時觸發的委派。state:使用者自訂狀態物件,常傳遞 Socket 本身。public Socket EndAccept(IAsyncResult asyncResult);
public Socket EndAccept(out byte[] buffer, IAsyncResult asyncResult);
public Socket EndAccept(out byte[] buffer, out int bytesTransferred, IAsyncResult asyncResult);
| 多載 | 用途 |
|---|---|
| 第 1 種 | 最常用,單純取得新連線的 Socket |
| 第 2 種 | 同時取得新連線與連線建立時隨附的初始資料(需啟用 SocketOptionName.AcceptConnection) |
| 第 3 種 | 更進一步取得已傳輸位元組數 |
asyncResult:儲存非同步作業狀態與使用者資料。out buffer / out bytesTransferred:類似 ref,但強調「輸出」語意,呼叫前無需初始化。private AsyncCallback callbackOnAccept;
private Socket listener;
public void StartServer()
{
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, 8888));
listener.Listen(100);
callbackOnAccept = new AsyncCallback(OnAccept);
listener.BeginAccept(callbackOnAccept, listener); // 開始第一次非同步接受
}
private void OnAccept(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket client = listener.EndAccept(ar); // 取得新連線
// 立即啟動下一次接受,形成循環
listener.BeginAccept(callbackOnAccept, listener);
// 這裡處理 client 通訊(可再用 BeginReceive/EndReceive)
Console.WriteLine($"Client connected: {client.RemoteEndPoint}");
}
state 傳遞 listener 讓回呼能持續接受新連線。