Socket 是 TCP/IP 協定的程式介面,是網路通訊的端點。本文系統整理同步/非同步 Socket 模式、多執行緒處理、核心 API 與完整範例,作為 C# 網路程式開發的參考手冊。
| 列舉 | 常用值 | 說明 |
|---|---|---|
| AddressFamily | InterNetwork (IPv4), InterNetworkV6 (IPv6) | 定址方案 |
| SocketType | Stream (TCP), Dgram (UDP), Raw | 通訊語意 |
| ProtocolType | Tcp, Udp | 協定 |
// IPEndPoint: IP + Port
var ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000);
// DNS 解析
IPHostEntry entry = Dns.GetHostEntry("www.example.com");
IPAddress ip = entry.AddressList[0];
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class SyncServer
{
Socket _listener;
Thread _thread;
public void Start()
{
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(new IPEndPoint(IPAddress.Any, 8000));
_listener.Listen(50);
_thread = new Thread(ListenLoop) { IsBackground = true };
_thread.Start();
}
void ListenLoop()
{
while (true)
{
try
{
Socket client = _listener.Accept(); // 阻塞等待
byte[] buffer = new byte[1024];
int received = client.Receive(buffer);
string msg = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"收到: {msg} from {client.RemoteEndPoint}");
// 回應
client.Send(Encoding.UTF8.GetBytes("OK"));
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (SocketException ex) { Console.WriteLine(ex); }
}
}
public void Stop()
{
_listener?.Close();
_thread?.Join(1000);
}
}
class SyncClient
{
public void SendMessage(string ip, int port, string message)
{
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
client.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
client.Send(Encoding.UTF8.GetBytes(message));
byte[] buffer = new byte[1024];
int received = client.Receive(buffer);
Console.WriteLine($"回應: {Encoding.UTF8.GetString(buffer, 0, received)}");
}
}
}
BeginConnect/EndConnectBeginSend/EndSendBeginReceive/EndReceiveBeginAccept/EndAcceptclass AsyncServer
{
Socket _listener;
const int BufferSize = 4096;
public void Start(int port)
{
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(new IPEndPoint(IPAddress.Any, port));
_listener.Listen(100);
_listener.BeginAccept(AcceptCallback, _listener);
}
void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket client = listener.EndAccept(ar);
// 立即投遞下一個 Accept
listener.BeginAccept(AcceptCallback, listener);
// 為新客戶端投遞 Receive
var state = new StateObject { Client = client, Buffer = new byte[BufferSize] };
client.BeginReceive(state.Buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, state);
}
void ReceiveCallback(IAsyncResult ar)
{
var state = (StateObject)ar.AsyncState;
Socket client = state.Client;
try
{
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
string msg = Encoding.UTF8.GetString(state.Buffer, 0, bytesRead);
Console.WriteLine($"收到: {msg}");
// 回應 (同步發送簡化)
client.Send(Encoding.UTF8.GetBytes("ACK"));
// 繼續接收
client.BeginReceive(state.Buffer, 0, BufferSize, SocketFlags.None, ReceiveCallback, state);
}
else { client.Close(); }
}
catch { client.Close(); }
}
class StateObject { public Socket Client; public byte[] Buffer; }
}
.NET 4.5+ 推薦使用 Task 為基礎的非同步模式:
public async Task HandleClientAsync(Socket client)
{
var buffer = new byte[4096];
while (true)
{
int read = await client.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None);
if (read == 0) break;
string msg = Encoding.UTF8.GetString(buffer, 0, read);
await client.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes("ACK")), SocketFlags.None);
}
client.Close();
}
| 類別/方法 | 用途 |
|---|---|
Thread | 手動建立/控制執行緒 |
ThreadPool.QueueUserWorkItem | 佇列工作項目至執行緒池 |
Task / Task<T> | 現代非同步工作單元 |
lock / Monitor | 同步鎖 |
Interlocked | 原子操作 |
AutoResetEvent / ManualResetEvent | 執行緒訊號 |
Semaphore / SemaphoreSlim | 資源計數同步 |
var t = new Thread(Work) { IsBackground = true };
t.Start();
Thread.Sleep(1000); // 休眠
t.Join(2000); // 等待結束 (含逾時)
t.Interrupt(); // 中斷阻塞
t.Abort(); // 強制終止 (不推薦,.NET Core 不支援)
SocketAsyncEventArgs 或 MemoryPool 減少配置。Shutdown(SocketShutdown.Send) → 讀取剩餘資料 → Close()。socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true)。SocketException、ObjectDisposedException、OperationCanceledException。async/await + System.IO.Pipelines 或 Kestrel/SignalR 高階框架。Begin/End) 與同步阻塞模式的差異與遷移路徑。SocketAsyncEventArgs、ValueTask、Memory<T>、IOCompletionPort 原生整合。Socket 程式設計的核心不在 API 呼叫,而在於協定設計、併發控制、失敗處理、資源管理四大工程課題。掌握基礎,方能駕馭複雜。