线程池和文件下载服务器

如果设计一个服务器程序,每当处理用户请求时,都开始一个线程,将会在一定程序上消耗服务器的资源。为此,一个最好的解决方法就是在服务器启动之前,事先创建一些线程对象,然后,当处理客户端请求时,就从这些建好的线程中获得线程对象,并处理请求。保存这些线程对象的结构就叫做线程池。

C#中可以通过System.Threading.ThreadPool类来实现,在默认情况下,ThreadPool最大可建立500个工作线程和1000I/O线程(根据机器CPU个数和.net framework版本的不同,这些数据可能会有变化)。下面是一个用C#从线程池获得线程的例子:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> 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获得的线程都是后台线程。

下面的程序是我设计的一个下载文件服务器的例子。这个例子从ThreadPool获得线程,并处理相应的客户端请求。

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.IO;

namespace MyThread
{
class FileServer
{
private Stringroot;
private ThreadlistenerThread;

private void worker( object state)
{
TcpClientclient
= state as TcpClient;
try
{

client.ReceiveTimeout
= 2000 ;
Streamstream
= client.GetStream();
System.IO.StreamReadersr
= new StreamReader(stream);
Stringline
= sr.ReadLine();
String[]array
= line.Split( ' ' );
Stringpath
= array[ 1 ].Replace( ' / ' , ' // ' );
Stringfilename
= root + path;
if (File.Exists(filename)) // 如果下载文件存在,开始下载这个文件
{
FileStreamfileStream
= new FileStream(filename,FileMode.Open,FileAccess.Read,
FileShare.Read);
byte []buffer = new byte [ 8192 ]; // 每次下载8K
int count = 0 ;
StringresponseHeader
= " HTTP/1.1200OK/r/n " +
" Content-Type:application/octet-stream/r/n " +
" Content-Disposition:attachment;filename= " +
filename.Substring(filename.LastIndexOf( " // " ) + 1 ) + " /r/n/r/n " ;
byte []header = ASCIIEncoding.ASCII.GetBytes(responseHeader);
stream.Write(header,
0 ,header.Length);
while ((count = fileStream.Read(buffer, 0 ,buffer.Count())) > 0 )
{
stream.Write(buffer,
0 ,count);
}
Console.WriteLine(filename
+ " 下载完成 " );
}
else // 文件不存在,输出提示信息
{
Stringresponse
= " HTTP/1.1200OK/r/nContent-Type:text/plain;charset=utf-8/r/n/r/n文件不存在 " ;
byte []buffer = ASCIIEncoding.UTF8.GetBytes(response);
stream.Write(buffer,
0 ,buffer.Length);
}

}
catch (Exceptione)
{
Console.WriteLine(e.Message);
}
finally
{
if (client != null )
{
client.Close();
}
}
}

private void listener()
{
TcpListenerlistener
= new TcpListener( 1234 );
listener.Start();
// 开始监听客户端请求
TcpClientclient = null ;

while ( true )
{
client
= listener.AcceptTcpClient();
client.ReceiveTimeout
= 2000 ;
ThreadPool.QueueUserWorkItem(worker,client);
// 从线程池中获得一个线程来处理客户端请求
}
}
public FileServer(Stringroot)
{
this .root = root;
}
public void start()
{
listenerThread
= new Thread(listener);
listenerThread.Start();
// 开始运行监听线程
}
}
}

 

FileServer类的使用方法:

FileServer fs = new FileServer(“d://download”);

fs.start();// 端口为1234

如果d:"download目录中有一个叫aa.exe的文件,在浏览器中输入如下的地址可下载:
http://localhost:1234/aa.exe

下图为下载对话框:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值