上一篇使用原始 Socket 類別建立 TCP 通訊。.NET 提供 TcpListener (伺服端) 與 TcpClient (客戶端) 兩個助手類別,大幅簡化程式碼,適合初學者快速上手。
// 原版 Socket 需 4 步驟
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 6001);
TcpListener server = new TcpListener(ipep);
server.Start();
// 更簡單:只指定 Port
TcpListener server = new TcpListener(6001);
server.Start();
while (true)
{
try
{
// 阻塞等待連接,回傳 TcpClient
TcpClient client = server.AcceptTcpClient();
// 或取得原始 Socket (進階用途)
// Socket socket = server.AcceptSocket();
// 派遣處理 (配合執行緒池更佳)
ThreadPool.QueueUserWorkItem(HandleClient, client);
}
catch (Exception ex)
{
// 錯誤處理
}
}
private void HandleClient(object state)
{
TcpClient client = (TcpClient)state;
NetworkStream ns = client.GetStream(); // 關鍵:取得網路串流
// 發送歡迎訊息
byte[] data = Encoding.ASCII.GetBytes("Welcome to server");
ns.Write(data, 0, data.Length);
// 接收迴圈
byte[] buffer = new byte[1024];
while (true)
{
int read = ns.Read(buffer, 0, buffer.Length);
if (read == 0) break; // 連線關閉
string msg = Encoding.ASCII.GetString(buffer, 0, read);
Console.WriteLine($"收到: {msg}");
}
client.Close();
}
TcpClient client = new TcpClient();
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001);
client.Connect(ipep); // 或 client.Connect("127.0.0.1", 6001);
NetworkStream ns = client.GetStream();
// 接收歡迎訊息
byte[] buffer = new byte[1024];
int read = ns.Read(buffer, 0, buffer.Length);
string welcome = Encoding.ASCII.GetString(buffer, 0, read);
// 發送指令
string cmd = "Hello Server";
byte[] data = Encoding.ASCII.GetBytes(cmd);
ns.Write(data, 0, data.Length);
client.Close();
| 功能 | Socket (原始) | TcpListener/TcpClient |
|---|---|---|
| 建立監聽 | 4 步驟 (Socket, Bind, Listen) | 2 行 (new TcpListener, Start) |
| 接受連接 | Accept() → Socket | AcceptTcpClient() → TcpClient |
| 資料收發 | Send/Receive | NetworkStream.Read/Write |
| 編碼轉換 | 手動 Encoding | 手動 Encoding (相同) |
| 適用階段 | 進階控制、非同步、原始協定 | 快速原型、教學、標準 TCP |
NetworkStream ns = client.GetStream();
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns) { AutoFlush = true };
// 發送
sw.WriteLine("Hello"); // 自動加換行
// 接收
string line = sr.ReadLine(); // 讀一行 (含邊界處理)
解決訊息邊界問題,但訊息內容不可含換行符。
本文配套原始碼 (含 WinForms 介面示範)