|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
听03很多师兄说主讲老师杭城方讲课很差就连旁听也没有去了)多线程 良多人都有过利用收集蚂蚁或收集慢车软件下载互联网文件的履历,这些软件的利用能够年夜年夜减速互联网上文件的传输速率,削减文件传输的工夫。这些软件为何有云云年夜的魔力呢?其次要缘故原由是这些软件都接纳了多线程下载和断点续传手艺。假如我们本人来编写一个相似如许的程序,也可以疾速的在互联网高低载文件,那必定长短常兴奋的事变。上面我就讲一讲怎样使用C#言语编写一个撑持多线程下载文件的程序,你会看到使用C#言语编写收集应程序是何等的简单,从中也能体味到C#言语中壮大的收集功效。
起首先容一下HTTP协定,HTTP亦即HpyerTextTransferProtocal的缩写,它是古代互联网上最主要的一种收集协定,超文本传输协定位于TCP/IP协定的使用层,是一个面向无毗连、复杂、疾速的C/S布局的协定。HTTP的事情历程大致上分毗连、哀求、呼应和断开毗连四个步骤。C#言语对HTTP协定供应了优秀的撑持,在.NET类库中供应了WebRequest和WebResponse类,这两个类都包括在System.Net定名空间中,使用这两个类能够完成良多初级的收集功效,本文中多线程文件下载就是使用这两个类完成的。WebRequest和WebResponse都是笼统基类,因而在程序中不克不及间接作为工具利用,必需被承继,实践利用中,可依据URI参数中的URI前缀选用它们符合的子类,关于HTTP这类URI,HttpWebRequest和HttpWebResponse类能够用于处置客户程序同WEB服务器之间的HTTP通信。
HttpWebRequest类完成了良多经由过程HTTP会见WEB服务器上文件的初级功效。HttpWebRequest类对WebRequest中界说的属性和办法供应撑持,HttpWebRequest将发送到Internet资本的大众HTTP标头的值公然为属性,由办法或体系设置,经常使用的由属性或办法设置的HTTP标头为:承受,由Accept属性设置,毗连,由Connection属性和KeepAlive属性设置,Content-Length,由ContentLength属性设置,Content-Type,由ContentType属性设置,局限,由AddRange办法设置.实践利用中是将标头信息准确设置后,传送到WEB服务器,WEB服务器依据请求作出回应。
HttpWebResponse类承继自WebResponse类,专门处置从WEB服务器前往的HTTP呼应,这个类完成了良多办法,具有良多属性,能够周全处置吸收到的互联网信息。在HttpWebResponse类中,关于年夜多半通用的HTTP标头字段,都有自力的属性与其对应,程序员能够经由过程这些属性便利的会见位于HTTP吸收报文标头字段中的信息,本例顶用到的HttpWebResponse类属性为:ContentLength既吸收内容的长度。
有了以上的懂得后,上面看看这两个类的用法,要创立HttpWebRequest工具,不要间接利用HttpWebRequest的机关函数,而要利用WebRequest.Create办法初始化一个HttpWebRequest实例,如:
HttpWebRequesthwr=(HttpWebRequest)WebRequest.Create(http://www.ckuyun.com/);
创立了这个工具后,就能够经由过程HttpWebRequest属性,设置良多HTTP标头字段的内容,如hwr.AddRange(100,1000);设置吸收工具的局限为100-1000字节。
HttpWebReques工具利用GetResponse()办法时,会前往一个HttpWebResponse工具,为提出HTTP前往报文信息,必要利用HttpWebResponse的GetResponseStream()办法,该办法前往一个Stream工具,能够读取HTTP前往的报文,如:起首界说一个Strean工具publicSystem.IO.Streamns;然后ns=hwr.GetResponse().GetResponseStream();便可创立Stream工具。有了以上的筹办常识后上面入手下手计划我们的多线程互联网文件的下载程序,起首翻开VisualStudio.Net集成开辟情况,选择“文件”、“新建”、“项目”,然后选择“VisualC#项目”,在导游右侧列表框当选中“Windows使用程序”,输出项目称号,如本例为:httpftp,然后选择“断定”按钮,导游主动天生了一个Windows使用程序项目。起首翻开窗口计划器计划使用程序窗口,增添以下控件:
一个列表框listBox1三个文本标签label1-label3三个文本框textBox1-textBox3一个入手下手吸收按钮button1计划好的窗口以下图:
控件界说代码是:
publicSystem.Windows.Forms.ListBoxlistBox1;
privateSystem.Windows.Forms.Labellabel1;
privateSystem.Windows.Forms.TextBoxtextBox1
privateSystem.Windows.Forms.Buttonbutton1;
privateSystem.Windows.Forms.Labellabel2;
privateSystem.Windows.Forms.TextBoxtextBox2;
privateSystem.Windows.Forms.Labellabel3;
privateSystem.Windows.Forms.TextBoxtextBox3;
privateSystem.Windows.Forms.Labellabel4;
privateSystem.Windows.Forms.TextBoxtextBox4;
翻开Form1的代码编纂器,增添以下的定名空间:
usingSystem.Net;//收集功效
usingSystem.IO;//流撑持
usingSystem.Threading;//线程撑持
增添以下的程序变量:
publicbool[]threadw;//每一个线程停止标记
publicstring[]filenamew;//每一个线程吸收文件的文件名
publicint[]filestartw;//每一个线程吸收文件的肇端地位
publicint[]filesizew;//每一个线程吸收文件的巨细
publicstringstrurl;//承受文件的URL
publicboolhb;//文件兼并标记
publicintthread;//历程数
界说一个HttpFile类,用于办理吸收线程,其代码以下:
publicclassHttpFile
{
publicForm1formm;
publicintthreadh;//线程代号
publicstringfilename;//文件名
publicstringstrUrl;//吸收文件的URL
publicFileStreamfs;
publicHttpWebRequestrequest;
publicSystem.IO.Streamns;
publicbyte[]nbytes;//吸收缓冲区
publicintnreadsize;//吸收字节数
publicHttpFile(Form1form,intthread)//机关办法
{
formm=form;
threadh=thread;
}
~HttpFile()//析构办法
{
formm.Dispose();
}
publicvoidreceive()//吸收线程
{
filename=formm.filenamew[threadh];
strUrl=formm.strurl;
ns=null;
nbytes=newbyte[512];
nreadsize=0;
formm.listBox1.Items.Add("线程"+threadh.ToString()+"入手下手吸收");
fs=newFileStream(filename,System.IO.FileMode.Create);
try
{
request=(HttpWebRequest)HttpWebRequest.Create(strUrl);
//吸收的肇端地位及吸收的长度
request.AddRange(formm.filestartw[threadh],
formm.filestartw[threadh]+formm.filesizew[threadh]);
ns=request.GetResponse().GetResponseStream();//取得吸收流
nreadsize=ns.Read(nbytes,0,512);
while(nreadsize>0)
{
fs.Write(nbytes,0,nreadsize);
nreadsize=ns.Read(nbytes,0,512);
formm.listBox1.Items.Add("线程"+threadh.ToString()+"正在吸收");
}
fs.Close();
ns.Close();
}
catch(Exceptioner)
{
MessageBox.Show(er.Message);
fs.Close();
}
formm.listBox1.Items.Add("历程"+threadh.ToString()+"吸收终了!");
formm.threadw[threadh]=true;
}
}
该类和Form1类处于一致定名空间,但不包括在Form1类中。上面界说“入手下手吸收”按钮控件的事务呼应函数:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
DateTimedt=DateTime.Now;//入手下手吸收工夫
textBox1.Text=dt.ToString();
strurl=textBox2.Text.Trim().ToString();
HttpWebRequestrequest;
longfilesize=0;
try
{
request=(HttpWebRequest)HttpWebRequest.Create(strurl);
filesize=request.GetResponse().ContentLength;//获得方针文件的长度
request.Abort();
}
catch(Exceptioner)
{
MessageBox.Show(er.Message);
}
//吸收线程数
thread=Convert.ToInt32(textBox4.Text.Trim().ToString(),10);
//依据线程数初始化数组
threadw=newbool[thread];
filenamew=newstring[thread];
filestartw=newint[thread];
filesizew=newint[thread];
//盘算每一个线程应当吸收文件的巨细
intfilethread=(int)filesize/thread;//均匀分派
intfilethreade=filethread+(int)filesize%thread;//残剩部分由最初一个线程完成
//为数组赋值
for(inti=0;i<thread;i++)
{
threadw[i]=false;//每一个线程形态的初始值为假
filenamew[i]=i.ToString()+".dat";//每一个线程吸收文件的一时文件名
if(i<thread-1)
{
filestartw[i]=filethread*i;//每一个线程吸收文件的肇端点
filesizew[i]=filethread-1;//每一个线程吸收文件的长度
}
else
{
filestartw[i]=filethread*i;
filesizew[i]=filethreade-1;
}
}
//界说线程数组,启动吸收线程
Thread[]threadk=newThread[thread];
HttpFile[]httpfile=newHttpFile[thread];
for(intj=0;j<thread;j++)
{
httpfile[j]=newHttpFile(this,j);
threadk[j]=newThread(newThreadStart(httpfile[j].receive));
threadk[j].Start();
}
//启动兼并各线程吸收的文件线程
Threadhbth=newThread(newThreadStart(hbfile));
hbth.Start();
}
兼并文件的线程hbfile界说在Form1类中,界说以下:
publicvoidhbfile()
{
while(true)//守候
{
hb=true;
for(inti=0;i<thread;i++)
{
if(threadw[i]==false)//有未停止线程,守候
{
hb=false;
Thread.Sleep(100);
break;
}
}
if(hb==true)//一切线程均已停止,中断守候,
{
break;
}
}
FileStreamfs;//入手下手兼并
FileStreamfstemp;
intreadfile;
byte[]bytes=newbyte[512];
fs=newFileStream(textBox3.Text.Trim().ToString(),System.IO.FileMode.Create);
for(intk=0;k<thread;k++)
{
fstemp=newFileStream(filenamew[k],System.IO.FileMode.Open);
while(true)
{
readfile=fstemp.Read(bytes,0,512);
if(readfile>0)
{
fs.Write(bytes,0,readfile);
}
else
{
break;
}
}
fstemp.Close();
}
fs.Close();
DateTimedt=DateTime.Now;
textBox1.Text=dt.ToString();//停止工夫
MessageBox.Show("吸收终了!!!");
}
至此,一个多线程下载文件的程序就半途而废了,注重在输出当地文件名时,应按以下格局输出:“c: esthttpftpind.htm”,因””后的字符在C#中是本义字符,线程数并不是越年夜越好,一样平常5个线程就能够了,该程序在VisualStudio.Net2002开辟情况及Windowsxp操纵体系上经由过程。
感觉很多控件都必须自己去写代码;用了WebMatrix感觉也不是很好,毕竟没有很强的WYSIWYG效果。现在就不知道如何是好了。 |
|