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

C# 執行緒系列講座 (3):執行緒集區檔案下載伺服器核心代碼

     編輯:關於C語言

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 緩衝區流式傳輸,記憶體佔用恆定
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved