高併發伺服器開發首選非同步 Socket,效能遠優於同步阻塞模型。本文詳述監聽、接收、發送的非同步流程與關鍵程式碼模式。
| 場景 | 建議模型 |
|---|---|
| 用戶端 Socket | 同步 |
| 伺服端連線數少 | 同步 |
| 大量短連線 | 同步 |
| 伺服端大量長連線 | 非同步 |
Socket _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(_address, _port);
_listener.Bind(localEP);
_listener.Listen(100);
Thread _acceptThread = new Thread(AcceptWorkThread);
_acceptThread.Start();
private void AcceptWorkThread()
{
while (_isListening)
{
UserInfo info = new UserInfo(); // 自訂狀態物件
Socket client = _listener.Accept();
info.Socket = client;
// 投遞第一個非同步接收
client.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None,
ReceiveCallBack, info);
}
}
private void ReceiveCallBack(IAsyncResult ar)
{
UserInfo info = (UserInfo)ar.AsyncState;
Socket handler = info.Socket;
int readCount = 0;
try { readCount = handler.EndReceive(ar); }
catch (SocketException) { CloseSocket(info); return; }
if (readCount > 0)
{
byte[] data = new byte[readCount];
Buffer.BlockCopy(info.Buffer, 0, data, 0, readCount);
Analyzer(info, data); // 業務處理
// 投遞下一次接收 (關鍵:形成接收循環)
try
{
handler.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None,
ReceiveCallBack, info);
}
catch (SocketException) { CloseSocket(info); }
}
else // 收到 0 位元組 = 客戶端關閉
CloseSocket(info);
}
public void Send(Socket socket, byte[] message)
{
try
{
socket.BeginSend(message, 0, message.Length, SocketFlags.None,
SendCallBack, new UserInfo { Socket = socket });
}
catch (SocketException) { /* 處理錯誤 */ }
}
private void SendCallBack(IAsyncResult ar)
{
UserInfo info = (UserInfo)ar.AsyncState;
try { info.Socket.EndSend(ar); }
catch { /* 忽略或記錄 */ }
}
UserInfo 封裝 Socket、緩衝區、使用者資料,透過 AsyncState 在回呼間流轉。EndReceive 後必須再次 BeginReceive,維持持續接收。Accept 簡化邏輯,不影響效能(Accept 本身快速且非瓶頸)。SocketException 通常代表連線斷開,統一在 CloseSocket 清理資源。