TCP 同步用戶端核心程式碼
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
public partial class ClientForm : Form {
private void btnSend_Click(object sender, EventArgs e) {
SendMessage();
}
private void SendMessage() {
string ip = txtIP.Text;
string port = txtPort.Text;
if (!IPAddress.TryParse(ip, out var serverIP)) {
MessageBox.Show("Invalid IP");
return;
}
if (!int.TryParse(port, out var serverPort)) {
MessageBox.Show("Invalid Port");
return;
}
var endPoint = new IPEndPoint(serverIP, serverPort);
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) {
try {
socket.Connect(endPoint);
byte[] data = Encoding.UTF8.GetBytes(txtMessage.Text);
socket.Send(data);
socket.Shutdown(SocketShutdown.Both);
} catch (SocketException ex) {
MessageBox.Show($"Connection failed: {ex.Message}");
}
}
}
}
關鍵 API 解析
| 方法 | 用途 |
Connect(EndPoint) | 主動發起 TCP 連線,阻塞直到成功/失敗 |
Send(byte[]) | 發送資料,阻塞直到緩衝區寫入完成 |
Shutdown(SocketShutdown.Both) | 禁用收發,發送 FIN 封包,優雅關閉 |
Close() | 釋放 Socket 與底層控制代碼 |
using 陳述式優勢
- 確保
Dispose() 被呼叫(等同 Close())
- 即使發生例外也能釋放資源
- 避免佔用連接埠導致
Address already in use
常見問題與解決
| 問題 | 原因 | 解決 |
| 連線逾時 | 防火牆、IP/Port 錯誤、伺服端未啟動 | 檢查防火牆規則、ping 測試、伺服端日誌 |
| 中文亂碼 | 編碼不一致 | 雙方統一 Encoding.UTF8 |
| 大資料截斷 | 單次 Send 不保證全發送 | 迴圈檢查回傳值,未發送完繼續 Send |
| 連線重置 | 伺服端主動關閉/異常 | 實作重連邏輯、心跳檢測 |
進階:完整發送迴圈
int totalSent = 0;
while (totalSent < data.Length) {
int sent = socket.Send(data, totalSent, data.Length - totalSent, SocketFlags.None);
if (sent == 0) throw new SocketException((int)SocketError.ConnectionReset);
totalSent += sent;
}
同步 vs 非同步選擇指南
- 同步:簡單工具、低併發、測試驗證、UI 執行緒外的背景工作
- 非同步:高併發伺服器、UI 響應、大量連線、.NET Core 高效能場景
下一步
請參考系列前文:
(一) 同步 Socket 基礎架構
(二) 主機解析/綁定/發送
(三) Send/Receive 多載詳解
(四) 執行緒建立/掛起/恢復/Join
(五) 執行緒銷毀/Unix 網路模型
(七) 伺服端實作/Socket 類型