本文展示基於 TcpClient/TcpListener 與 NetworkStream/StreamReader/StreamWriter 的高層封裝範例,簡化資料讀寫為文字行導向操作。適合快速原型開發與教學參考。
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
namespace QQ
{
public partial class Tcpclient : Form
{
private StreamWriter write;
private NetworkStream stream;
private TcpClient tcpclient;
public Tcpclient() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e)
{
try
{
tcpclient = new TcpClient(AddressFamily.InterNetwork);
tcpclient.Connect("127.0.0.1", 8000); // 同步連線
stream = tcpclient.GetStream(); // 取得網路串流
write = new StreamWriter(stream); // 文字寫入器
write.WriteLine(this.textBox1.Text); // 寫入一行 (含換行)
write.Flush(); // 強制發送緩衝區
}
catch { /* 實務應記錄異常 */ }
}
}
}
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Net;
using System.Windows.Forms;
namespace QQ
{
public partial class Tcpserver : Form
{
int port = 8000;
private Thread threadRead;
private TcpListener tcpListen;
private bool blistener = true;
private NetworkStream stream;
private StreamReader read;
private TcpClient client;
private delegate void listbox_show(string str);
listbox_show listboxshow;
public Tcpserver()
{
InitializeComponent();
listboxshow = new listbox_show(show);
}
private void Listen()
{
try
{
tcpListen = new TcpListener(8000); // 監聽埠 8000
tcpListen.Start(); // 開始監聽
client = tcpListen.AcceptTcpClient(); // 同步接受連線
stream = client.GetStream();
read = new StreamReader(stream); // 文字讀取器
while (blistener)
{
string message = read.ReadLine(); // 讀取一行 (阻塞至換行)
if (message == "STOP")
{
tcpListen.Stop();
stream.Close();
read.Close();
threadRead.Abort(); // 強制終止執行緒 (不推薦生產用)
return;
}
string sTime = DateTime.Now.ToShortDateString();
listBox1.Invoke(listboxshow, sTime + " " + message);
}
}
catch (System.Security.SecurityException)
{
MessageBox.Show("監聽失敗!", "錯誤");
}
}
private void show(string str) { this.listBox1.Items.Add(str); }
private void button1_Click(object sender, EventArgs e)
{
threadRead = new Thread(new ThreadStart(Listen));
threadRead.Start();
this.button1.Enabled = false;
}
}
}
| 維度 | Socket (上篇) | TcpClient/TcpListener (本篇) |
|---|---|---|
| 抽象層級 | 底層 Berkeley Socket 封裝 | 應用層高階封裝 |
| 資料處理 | 位元組陣列 byte[] | 串流 NetworkStream + 文字讀寫器 |
| 協定支援 | TCP/UDP/Raw 任意 | 僅 TCP |
| 訊息邊界 | 無 (需自行框架) | 行導向 ReadLine/WriteLine 內建 |
| 編碼處理 | 手動 Encoding.GetBytes/GetString | StreamReader/Writer 內建編碼 (預設 UTF-8) |
| 適用場景 | 高效能、自定義協定、非 TCP | 快速開發、文字協定、HTTP/POP3/SMTP 類 |
// 客戶端
tcpclient.Connect("127.0.0.1", 8000); // 阻塞直到連線成功或逾時
// 伺服器端
tcpListen.Start();
client = tcpListen.AcceptTcpClient(); // 阻塞直到有客戶端連線
WriteLine 自動附加 Environment.NewLine,Flush 確保立即發送ReadLine 阻塞讀取直到遇到換行符if (message == "STOP") {
tcpListen.Stop(); // 停止監聽新連線
stream.Close(); // 關閉串流
read.Close(); // 關閉讀取器
threadRead.Abort(); // 強制終止執行緒 (僅示範,生產請用 CancellationToken)
return;
}
AcceptTcpClient → ReadLine 迴圈BeginAcceptTcpClient/EndAcceptTcpClient 或 Task.Run 非同步模式StreamWriter/StreamReader 預設 Encoding.UTF8 (無 BOM)Encoding.Default (ANSI) 更推薦| 問題 | 原因 | 改進 |
|---|---|---|
| 單客戶端阻塞 | 單執行緒循序 Accept/Read | 非同步 Accept + 每客戶端獨立處理執行緒/Task |
| Thread.Abort() 風險 | 強制終止可能損壞資源狀態 | 使用 CancellationToken + 迴圈檢查優雅退出 |
| 無訊息長度限制 | ReadLine 讀到換行為止 | 加入最大行長度檢查,防止記憶體耗盡 |
| 異常吞沒 | catch { } 空白處理 | 記錄異常日誌,區分暫時性/永久性錯誤 |
TcpClient/TcpListener + StreamReader/Writer 提供簡潔的文字行導向 TCP 程式設計模型,適合快速原型、簡單協定、教學示範。生產環境高併發場景請採用非同步模式或成熟框架。