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

C# Socket 程式設計入門:TCP 伺服器與用戶端完整範例

     編輯:關於C#

TCP 通訊基礎

  • 伺服器:`TcpListener` 監聽端口 → `AcceptSocket`/`AcceptTcpClient` 等待連線 → `NetworkStream` 讀寫。
  • 用戶端:`TcpClient` 連線伺服器 → `GetStream` 取得 `NetworkStream` → 讀寫。
  • 資料協定:自訂訊息格式 (長度前綴、分隔符、序列化)。範例採「行為單位」`ReadLine`/`WriteLine`。

伺服器端完整程式碼


using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace TcpServerDemo
{
    class Program
    {
        static void Main()
        {
            const int port = 12345;
            var listener = new TcpListener(IPAddress.Any, port);
            listener.Start();
            Console.WriteLine($"伺服器啟動,監聽 {port}...");

            while (true) // 持續接受多個用戶端 (單執行緒示範)
            {
                using (var client = listener.AcceptTcpClient())
                using (var stream = client.GetStream())
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                using (var writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true })
                {
                    Console.WriteLine($"用戶端連線: {client.Client.RemoteEndPoint}");
                    
                    while (true)
                    {
                        string line = reader.ReadLine();
                        if (line == null) break; // 用戶端斷線
                        
                        Console.WriteLine($"收到: {line}");
                        string reply = line.ToUpper() + " [SERVER ECHO]";
                        writer.WriteLine(reply);
                        Console.WriteLine($"回覆: {reply}");
                    }
                }
                Console.WriteLine("用戶端斷線,等待下一個...");
            }
        }
    }
}

用戶端完整程式碼 (WinForms)


using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace TcpClientDemo
{
    public partial class ClientForm : Form
    {
        private TcpClient _client;
        private StreamReader _reader;
        private StreamWriter _writer;

        public ClientForm() => InitializeComponent();

        private async void btnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                _client = new TcpClient();
                await _client.ConnectAsync("127.0.0.1", 12345);
                var stream = _client.GetStream();
                _reader = new StreamReader(stream, Encoding.UTF8);
                _writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true };
                
                AppendLog("已連線至伺服器");
                btnConnect.Enabled = false;
                btnSend.Enabled = true;
                _ = ReceiveLoopAsync(); // 火力全開接收迴圈
            }
            catch (Exception ex)
            {
                MessageBox.Show($"連線失敗: {ex.Message}");
            }
        }

        private async Task ReceiveLoopAsync()
        {
            try
            {
                while (true)
                {
                    string line = await _reader.ReadLineAsync();
                    if (line == null) break;
                    AppendLog($"[伺服器] {line}");
                }
            }
            catch (IOException) { /* 連線中斷 */ }
            catch (ObjectDisposedException) { /* 已關閉 */ }
            finally
            {
                Invoke(() => { btnConnect.Enabled = true; btnSend.Enabled = false; });
                AppendLog("連線已斷開");
            }
        }

        private async void btnSend_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtInput.Text)) return;
            try
            {
                await _writer.WriteLineAsync(txtInput.Text);
                AppendLog($"[我] {txtInput.Text}");
                txtInput.Clear();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"發送失敗: {ex.Message}");
            }
        }

        private void AppendLog(string msg)
        {
            if (InvokeRequired) Invoke(new Action(() => AppendLog(msg)));
            else lstLog.Items.Add($"[{DateTime.Now:HH:mm:ss}] {msg}");
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            _writer?.Dispose();
            _reader?.Dispose();
            _client?.Dispose();
            base.OnFormClosing(e);
        }
    }
}

關鍵類別對照

類別角色關鍵方法
TcpListener伺服器監聽器Start(), AcceptTcpClient(), AcceptTcpClientAsync()
TcpClient用戶端連線器Connect/ConnectAsync, GetStream(), Close()
NetworkStream雙向資料流Read/Write/ReadAsync/WriteAsync, Flush()
StreamReader/Writer文字編碼包裝ReadLine/WriteLine/ReadLineAsync/WriteLineAsync

進階主題

  • 非阻塞/高併發:`SocketAsyncEventArgs` / `Pipe` / `Channels` / `Kestrel` (ASP.NET Core 內建)。
  • 訊息框架:長度前綴 (4 bytes length + payload) 或 `MessagePack`/`Protobuf` 序列化。
  • SSL/TLS:`SslStream` 包裝 `NetworkStream`,伺服器需 `X509Certificate2`。
  • 優雅關閉:`Socket.Shutdown(SocketShutdown.Both)` → `Close()`,雙方協議結束。
  • 心跳/保活:定時發送 `PING`/`PONG` 或啟用 `Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true)`。

總結

C# Socket 程式設計核心在於 **`TcpListener`/`TcpClient` + `NetworkStream` + `StreamReader/Writer`** 三層封裝。掌握同步/非同步讀寫、連線生命週期管理、編碼處理與例外處理,即可建構穩健的 TCP 通訊應用。高併發、生產級專案建議直接使用 **ASP.NET Core / gRPC / SignalR** 等成熟框架。

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