如果设计一个服务器程序,每当处理用户请求时,都开始一个线程,将会在一 定程序上消耗服务器的资源。为此,一个最好的解决方法就是在服务器启动之前 ,事先创建一些线程对象,然后,当处理客户端请求时,就从这些建好的线程中 获得线程对象,并处理请求。保存这些线程对象的结构就叫做线程池。
在C#中可以通过System.Threading.ThreadPool类来实现,在默认情况下, ThreadPool最大可建立500个工作线程和1000个I/O线程(根据机器CPU个数和.net framework版本的不同,这些数据可能会有变化)。下面是一个用C#从线程池获得 线程的例子:
private static void execute(object state){ Console.WriteLine(state); }static void Main(string[] args){ int workerThreads; int completionPortThreads; ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); Console.WriteLine(workerThreads); Console.WriteLine(completionPortThreads); ThreadPool.QueueUserWorkItem(execute,"线程1"); // 从线程池中得到一个线程,并运行execute ThreadPool.QueueUserWorkItem(execute, "线程2"); ThreadPool.QueueUserWorkItem(execute, "线程3"); Console.ReadLine();}下图为上面代 码的运行结果。
要注意的是,使用ThreadPool获得的线程都是后台线程。
1 public class FileServer
2 {
3 private String root;
4 private Thread listenerThread;
5 private void worker(object state)
6 {
7 TcpClient client = state as TcpClient;
8 try
9 {
10 client.ReceiveTimeout = 2000;
11 Stream stream = client.GetStream();
12 System.IO.StreamReader sr = new StreamReader(stream);
13 String line = sr.ReadLine();
14 String[] array = line.Split(' ');
15 String path = array[1].Replace('/', '\\');
16 String filename = root + path;
17 if (File.Exists(filename)) // 如果下载文件存在,开始下载这个文件
18 {
19 FileStream fileStream =
20 new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
21 byte[] buffer = new byte[8192]; // 每次下载8K
22 int count = 0;
23 String responseHeader = "HTTP/1.1 200 OK\r\n"
24 + "Content-Type:application/octet-stream\r\n"
25 + "Content-Disposition:attachment;filename="
26 + filename.Substring(filename.LastIndexOf("\\") + 1) + "\r\n\r\n";
27 byte[] header = ASCIIEncoding.ASCII.GetBytes(responseHeader);
28 stream.Write(header, 0, header.Length);
29 while ((count = fileStream.Read(buffer, 0, buffer.Count())) > 0)
30 {
31 stream.Write(buffer, 0, count);
32 }
33 Console.WriteLine(filename + "下载完成");
34 }
35 else // 文件不存在,输出提示信息
36 {
37 String response = "HTTP/1.1 200 OK\r\nContent-Type:text/plain;charset=utf-8\r\n\r\n文件不存在";
38 byte[] buffer = ASCIIEncoding.UTF8.GetBytes(response);
39 stream.Write(buffer, 0, buffer.Length);
40 }
41 }
42 catch (Exception e)
43 {
44 Console.WriteLine(e.Message);
45 }
46 finally
47 {
48 if (client != null)
49 {
50 client.Close();
51 }
52 }
53 }
54 private void listener()
55 {
56 TcpListener listener = new TcpListener(new System.Net.IPAddress(new byte[]{127,0,0,1}), 1234);
57 listener.Start(); // 开始监听客户端请求
58 TcpClient client = null;
59 while (true)
60 {
61 client = listener.AcceptTcpClient();
62 client.ReceiveTimeout =2000;
63 ThreadPool.QueueUserWorkItem(worker, client); // 从线程池中获得一个线程来处理客户端请求
64 }
65 }
66 public FileServer(String root)
67 {
68 this.root= root;
69 }
70 public void start()
71 {
72 listenerThread = new Thread(listener);
73 listenerThread.Start(); // 开始运行监听线程
74 }
75 }
FileServer类的使用方法:
FileServer fs = new FileServer (“d:\\download”);
fs.start();// 端口为 1234
如果d:"download目录中有一个叫aa.exe的文件,在浏 览器中输入如下的地址可下载:
下图为下载对话框:
要注意的是,本程序并没有处理含有中文和其他特殊字符(如空格)的 url,因为,文件名要为英文名(不能有空格等特殊字符)。
文章来 源:http://www.cnblogs.com/nokiaguy/archive/2008/07/18/1246299.html
本文来自wuzhaopai.com编程技术网,转载请标明出处:http://www.wuzhaopai.com/html/NetSchool/AspDotNet/201107046884_3.html