承接上篇常用網路類別,本篇實作面向連接的 TCP Socket 通訊,含完整伺服端監聽與客戶端連接程式碼,可直接下載執行。
new IPEndPoint(IPAddress.Any, 6001) (Any 表示所有本機 IP)new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)socket.Bind(ipep)socket.Listen(10) (backlog=10)
while (true)
{
try
{
Socket clientSocket = serverSocket.Accept(); // 阻塞等待
Thread clientThread = new Thread(ReceiveData);
clientThread.Start(clientSocket); // 傳遞 clientSocket 給執行緒
}
catch (Exception ex) { /* 錯誤處理 */ }
}
private void ReceiveData(object state)
{
Socket client = (Socket)state;
byte[] buffer = new byte[1024];
// 取得客戶端端點資訊
IPEndPoint clientEP = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine($"Client connected: {clientEP.Address}:{clientEP.Port}");
// 發送歡迎訊息
string welcome = "Welcome to server";
byte[] data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length, SocketFlags.None);
// 接收迴圈
while (true)
{
try
{
int available = client.Available; // 可讀位元組數
if (available == 0) continue;
int read = client.Receive(buffer, 0, available, SocketFlags.None);
if (read == 0) break;
string msg = Encoding.ASCII.GetString(buffer, 0, read);
Console.WriteLine($"[{clientEP}] {msg}");
}
catch { break; }
}
}
new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001) + new Socket(...)clientSocket.Connect(ipep) (需伺服端已啟動監聽)
// 接收迴圈
while (true)
{
int available = clientSocket.Available;
if (available > 0)
{
byte[] buffer = new byte[1024];
int read = clientSocket.Receive(buffer, 0, available, SocketFlags.None);
string msg = Encoding.ASCII.GetString(buffer, 0, read);
Console.WriteLine($"Server: {msg}");
}
}
// 發送 (UI 事件中)
byte[] data = Encoding.ASCII.GetBytes(textBox.Text);
clientSocket.Send(data, data.Length, SocketFlags.None);
| 技術點 | 說明 |
|---|---|
| IPAddress.Any | 監聽所有本機網卡 IP,不需逐一指定 |
| ProtocolType.Tcp | 指定 TCP 協定 (面向連接、可靠、有序) |
| Listen(backlog) | 待連接佇列長度,超過則拒絕新連接 |
| Accept() | 阻塞直到有連接,回傳新 Socket 專責該連接 |
| 多執行緒 | 每連接一執行緒,主執行緒持續 Accept |
| Encoding.ASCII | 字串 ↔ 位元組轉換,網路傳輸必須是位元組 |
| RemoteEndPoint | 取得對方 IP:Port,型別轉換為 IPEndPoint |
| Available | 取得接收緩衝區可立即讀取的位元組數 |
BeginAccept/EndAccept、BeginReceive/EndReceive,避免執行緒佔用ThreadPool.QueueUserWorkItem 替代手動建立執行緒Available 非可靠邊界判斷,需協定層處理 (下下篇)