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}");
}
}
}
}
使用 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();
}
}
| 維度 | 同步 | 非同步 (APM) |
|---|---|---|
| 程式碼複雜度 | 低 | 高 |
| 執行緒使用 | 每連線一執行緒 | 少量執行緒處理大量連線 |
| 延展性 | 受限於執行緒池 | 極佳 (IOCP) |
| 錯誤處理 | try/catch 直觀 | 需在回呼中處理 |
| 現代替代方案 | async/await + Task (TAP 模式) | |
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 獲得更高效能與記憶體效率。