首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Socket 程式設計實戰 (一):基礎 Socket 同步通訊入門

     編輯:關於.NET

文章導讀

Socket 程式設計系列開幕篇,展示最基礎的 System.Net.Sockets.Socket 同步阻塞通訊客戶端/伺服器端完整程式碼。適合網路程式設計零基礎入門者建立第一性認知。

核心知識點

  • IPAddress、IPEndPoint、Socket 三大核心類別
  • 客戶端:Connect → Send → Close
  • 伺服器端:Bind → Listen → Accept → Receive → Close
  • BigEndianUnicode 編碼與跨執行緒 UI 更新

一、客戶端完整程式碼

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 = "還沒有信息";
            }
        }
    }
}

三、核心類別與流程圖解

1. 關鍵類別職責

類別職責關鍵方法
IPAddressIP 位址表示Parse(), AddressList
IPEndPointIP + 埠 = 網路端點建構子(IPAddress, port)
Socket通訊端點核心Bind, Listen, Accept, Connect, Send, Receive, Close

2. 伺服器端流程

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. 關閉

3. 客戶端流程

Socket socket = new Socket(InterNetwork, Stream, Tcp);
socket.Connect(new IPEndPoint(IP, Port)); // 1. 連線 (阻塞)
socket.Send(buffer);                      // 2. 傳送資料
socket.Close();                           // 3. 關閉

四、關鍵細節深度解析

1. 編碼選擇:BigEndianUnicode

  • Encoding.BigEndianUnicode = UTF-16BE (大端序)
  • 每字元固定 2 位元組,含字元序標記 (BOM: FE FF)
  • 注意:雙端必須使用相同編碼,否則解碼錯誤
  • 現代建議:統一使用 Encoding.UTF8 (變長、無 BOM、ASCII 相容、跨平台)

2. 緩衝區固定大小隱患

byte[] sendByte = new byte[64];
byte[] receiveByte = new byte[64];
  • 訊息超過 64 位元組會截斷/溢位
  • TCP 無訊息邊界,單次 Receive 不保證收到完整訊息
  • 正確做法:迴圈接收直到預期長度、或使用長度前綴/分隔符框架

3. 單連線處理限制

  • 伺服器 Accept() 只接受一個連線,隨後進入 Receive() 迴圈
  • 無法同時服務多個客戶端
  • 改進:while(true) { client = Accept(); ThreadPool.QueueUserWorkItem(HandleClient, client); }

4. 跨執行緒 UI 更新模式

// 定義委派
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 實現跨執行緒封送。

5. 連接埠硬編碼

  • Int32.Parse("1571")、Int32.Parse("1571") 雙端硬編碼
  • 實務應從設定檔/命令列/服務發現動態獲取

五、系列規劃預告

  1. 第 1 篇 (本文):基礎 Socket 同步阻塞通訊
  2. 第 2 篇:TcpClient/TcpListener 高層封裝 + 文字行協定
  3. 第 3 篇:Socket 進階 — 非同步模式、多客戶端併發、訊息框架

總結

本文展示最原始的 Socket 同步阻塞程式設計模式。雖簡單但含核心概念:端點建立、連線三次交握、資料序列化、執行緒模型、UI 執行緒親和性。掌握基礎,才能理解高層封裝與非同步模式的設計動機。

本文配套源碼下載
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved