FileServer 完整實作
class FileServer {
private string root;
private Thread listenerThread;
private void Worker(object state) {
TcpClient client = (TcpClient)state;
try {
client.ReceiveTimeout = 2000;
Stream stream = client.GetStream();
StreamReader sr = new StreamReader(stream);
string line = sr.ReadLine(); // GET /aa.exe HTTP/1.1
string[] parts = line.Split(' ');
string path = parts[1].Replace('/', '\\');
string file = root + path;
if (File.Exists(file)) {
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[] buf = new byte[8192];
int cnt;
string header = "HTTP/1.1 200 OK\r\n" +
"Content-Type:application/octet-stream\r\n" +
"Content-Disposition:attachment;filename=" + file.Substring(file.LastIndexOf('\\') + 1) + "\r\n\r\n";
byte[] hdr = Encoding.ASCII.GetBytes(header);
stream.Write(hdr, 0, hdr.Length);
while ((cnt = fs.Read(buf, 0, buf.Length)) > 0)
stream.Write(buf, 0, cnt);
Console.WriteLine(file + " 下載完成");
} else {
string resp = "HTTP/1.1 200 OK\r\nContent-Type:text/plain;charset=utf-8\r\n\r\n檔案不存在";
byte[] buf = Encoding.UTF8.GetBytes(resp);
stream.Write(buf, 0, buf.Length);
}
} catch (Exception ex) { Console.WriteLine(ex.Message); }
finally { client?.Close(); }
}
private void Listener() {
TcpListener ln = new TcpListener(1234);
ln.Start();
while (true) {
TcpClient client = ln.AcceptTcpClient();
client.ReceiveTimeout = 2000;
ThreadPool.QueueUserWorkItem(Worker, client); // 從集區取得執行緒
}
}
public FileServer(string root) { this.root = root; }
public void Start() {
listenerThread = new Thread(Listener);
listenerThread.Start();
}
}
關鍵設計
- 主執行緒
Listener 持續 AcceptTcpClient
- 每個連線丟給
ThreadPool.QueueUserWorkItem,避免頻繁建立/銷毀執行緒
- 回應標準 HTTP 標頭 + 二進位檔案內容,支援斷點續傳基礎
- 8KB 緩衝區流式傳輸,記憶體佔用恆定