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

C# 網路程式設計:同步與非同步 Socket I/O 完整實戰範例

     編輯:關於C語言

同步 Socket:伺服器/用戶端基本模型

伺服器端


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

public class SyncTcpServer
{
    public void Start()
    {
        var listener = new TcpListener(65000);
        listener.Start();
        Console.WriteLine("伺服器啟動,等待連線...");

        while (true)
        {
            using (var client = listener.AcceptSocket())
            using (var stream = new NetworkStream(client))
            using (var writer = new StreamWriter(stream) { AutoFlush = true })
            using (var reader = new StreamReader(@"C:\data.txt"))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    writer.WriteLine(line);
                }
                Console.WriteLine("檔案傳送完成");
            }
        }
    }
}

用戶端


public class SyncTcpClient
{
    public void Connect()
    {
        using (var client = new TcpClient("localhost", 65000))
        using (var stream = client.GetStream())
        using (var reader = new StreamReader(stream))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine($"收到: {line}");
            }
        }
    }
}

非同步 Socket:高延展性伺服器模型

使用 BeginRead/EndRead、BeginWrite/EndWrite 配合狀態物件,單一執行緒可處理大量連線。

伺服器端


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

public class AsyncTcpServer
{
    private TcpListener _listener;

    public void Start()
    {
        _listener = new TcpListener(65000);
        _listener.Start();
        _listener.BeginAcceptSocket(OnAccept, null);
        Console.WriteLine("非同步伺服器啟動");
        Console.ReadLine(); // 保持執行
    }

    private void OnAccept(IAsyncResult ar)
    {
        var socket = _listener.EndAcceptSocket(ar);
        _listener.BeginAcceptSocket(OnAccept, null); // 繼續接受下一個

        var handler = new ClientHandler(socket);
        handler.StartRead();
    }
}

class ClientHandler
{
    private readonly Socket _socket;
    private readonly NetworkStream _stream;
    private readonly byte[] _buffer = new byte[256];
    private readonly AsyncCallback _readCb;
    private readonly AsyncCallback _writeCb;

    public ClientHandler(Socket socket)
    {
        _socket = socket;
        _stream = new NetworkStream(socket);
        _readCb = OnReadComplete;
        _writeCb = OnWriteComplete;
    }

    public void StartRead()
    {
        _stream.BeginRead(_buffer, 0, _buffer.Length, _readCb, null);
    }

    private void OnReadComplete(IAsyncResult ar)
    {
        try
        {
            int bytesRead = _stream.EndRead(ar);
            if (bytesRead > 0)
            {
                string msg = Encoding.ASCII.GetString(_buffer, 0, bytesRead);
                Console.WriteLine($"收到 {bytesRead} bytes: {msg}");

                // 回傳相同資料
                _stream.BeginWrite(_buffer, 0, bytesRead, _writeCb, null);
            }
            else
            {
                Close();
            }
        }
        catch { Close(); }
    }

    private void OnWriteComplete(IAsyncResult ar)
    {
        try
        {
            _stream.EndWrite(ar);
            Console.WriteLine("回寫完成");
            _stream.BeginRead(_buffer, 0, _buffer.Length, _readCb, null); // 繼續讀取
        }
        catch { Close(); }
    }

    private void Close()
    {
        _stream?.Close();
        _socket?.Close();
        Console.WriteLine("連線關閉");
    }
}

非同步用戶端


public class AsyncTcpClient
{
    public void Connect()
    {
        var client = new TcpClient("localhost", 65000);
        var stream = client.GetStream();

        string msg = "Hello from async client!";
        var writer = new StreamWriter(stream) { AutoFlush = true };
        writer.WriteLine(msg);

        var reader = new StreamReader(stream);
        string response = reader.ReadLine();
        Console.WriteLine($"伺服器回應: {response}");

        stream.Close();
        client.Close();
    }
}

同步 vs 非同步比較

維度同步非同步 (APM)
程式碼複雜度低高
執行緒使用每連線一執行緒少量執行緒處理大量連線
延展性受限於執行緒池極佳 (IOCP)
錯誤處理try/catch 直觀需在回呼中處理
現代替代方案async/await + Task (TAP 模式)

現代化建議:使用 async/await


public async Task HandleClientAsync(TcpClient client)
{
    using (var stream = client.GetStream())
    using (var reader = new StreamReader(stream))
    using (var writer = new StreamWriter(stream) { AutoFlush = true })
    {
        string line;
        while ((line = await reader.ReadLineAsync()) != null)
        {
            Console.WriteLine($"收到: {line}");
            await writer.WriteLineAsync($"Echo: {line}");
        }
    }
}

.NET Core / .NET 5+ 建議使用 System.IO.Pipelines 獲得更高效能與記憶體效率。

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