Socket 程式設計系列開幕篇,展示最基礎的 System.Net.Sockets.Socket 同步阻塞通訊客戶端/伺服器端完整程式碼。適合網路程式設計零基礎入門者建立第一性認知。
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class net_client : Form
{
public net_client() { InitializeComponent(); }
private void btn_send_Click(object sender, EventArgs e)
{
Socket socket;
IPAddress HostIP = IPAddress.Parse("127.0.0.1");
IPEndPoint point;
try
{
point = new IPEndPoint(HostIP, Int32.Parse("1571"));
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(point); // 同步阻塞連線
byte[] sendByte = new byte[64];
string sendStr = this.textBox1.Text + "\r\n";
sendByte = Encoding.BigEndianUnicode.GetBytes(sendStr.ToCharArray());
socket.Send(sendByte, sendByte.Length, 0); // 同步阻塞傳送
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
using System;
using System.Text;
using System.Net;
using System.Threading;
using System.Diagnostics;
using System.Net.Sockets;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class net_server : Form
{
public net_server() { InitializeComponent(); }
// 跨執行緒 UI 更新委派
delegate void SetTextCallback(string text);
private void SetText(string text) { textBox1.AppendText(text + "\r\n"); }
IPAddress HostIP = IPAddress.Parse("127.0.0.1");
IPEndPoint point;
Socket socket;
Socket acceptedSocket;
private void button1_Click(object sender, EventArgs e)
{
try
{
point = new IPEndPoint(HostIP, Int32.Parse("1571"));
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(point); // 綁定本機端點
socket.Listen(50); // 開始監聽,佇列 50
Thread thread = new Thread(new ThreadStart(Process));
thread.Start(); // 背景執行緒處理連線
}
catch (Exception ey) { MessageBox.Show(ey.Message); }
}
private void Process()
{
acceptedSocket = socket.Accept(); // 同步阻塞接受連線
if (acceptedSocket.Connected)
{
byte[] receiveByte = new byte[64];
acceptedSocket.Receive(receiveByte, receiveByte.Length, 0); // 同步阻塞接收
string strInfo = Encoding.BigEndianUnicode.GetString(receiveByte);
// 跨執行緒更新 UI
this.Invoke(new SetTextCallback(SetText), new object[] { strInfo });
}
else
{
this.textBox1.Text = "還沒有信息";
}
}
}
}
| 類別 | 職責 | 關鍵方法 |
|---|---|---|
| IPAddress | IP 位址表示 | Parse(), AddressList |
| IPEndPoint | IP + 埠 = 網路端點 | 建構子(IPAddress, port) |
| Socket | 通訊端點核心 | Bind, Listen, Accept, Connect, Send, Receive, Close |
Socket socket = new Socket(InterNetwork, Stream, Tcp);
socket.Bind(new IPEndPoint(IP, Port)); // 1. 綁定
socket.Listen(Backlog); // 2. 監聽
Socket client = socket.Accept(); // 3. 接受 (阻塞)
client.Receive(buffer); // 4. 接收資料
client.Close(); // 5. 關閉
Socket socket = new Socket(InterNetwork, Stream, Tcp);
socket.Connect(new IPEndPoint(IP, Port)); // 1. 連線 (阻塞)
socket.Send(buffer); // 2. 傳送資料
socket.Close(); // 3. 關閉
Encoding.BigEndianUnicode = UTF-16BE (大端序)Encoding.UTF8 (變長、無 BOM、ASCII 相容、跨平台)byte[] sendByte = new byte[64];
byte[] receiveByte = new byte[64];
Accept() 只接受一個連線,隨後進入 Receive() 迴圈while(true) { client = Accept(); ThreadPool.QueueUserWorkItem(HandleClient, client); }// 定義委派
delegate void SetTextCallback(string text);
// 背景執行緒呼叫
this.Invoke(new SetTextCallback(SetText), new object[] { strInfo });
// UI 執行緒執行
private void SetText(string text) { textBox1.AppendText(text + "\r\n"); }
WinForms 控制項具有執行緒親和性,所有存取必須在 UI 執行緒,Control.Invoke 實現跨執行緒封送。
Int32.Parse("1571")、Int32.Parse("1571") 雙端硬編碼本文展示最原始的 Socket 同步阻塞程式設計模式。雖簡單但含核心概念:端點建立、連線三次交握、資料序列化、執行緒模型、UI 執行緒親和性。掌握基礎,才能理解高層封裝與非同步模式的設計動機。