C#实现HTTP协议:多线程文件传输
很多人都有过使用网络蚂蚁或网络快车互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间。这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载和断点续传技术。如果我们自己来编写一个类似这样的程序,也能够快速的在互联网上下载文件,那一定是非常愉快的事情。下面我就讲一讲如何利用C#语言编写一个支持多线程下载文件的程序,你会看到利用C#语言编写网络应用程序是多么的容易,从中也能体会到C#语言中强大的网络功能。
首先介绍一下HTTP协议, HTTP亦即Hpyer Text Transfer Protocal的缩写,它是现代互联网上最重要的一种网络协议,超文本传输协议位于TCP/IP协议的应用层,是一个面向无连接、简单、快速的C/S结构的协议。HTTP的工作过程大体上分连接、请求、响应和断开连接四个步骤。C#语言对HTTP协议提供了良好的支持,在类库中提供了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实例,如:
- HttpWebRequest hwr=(HttpWebRequest)WebRequest.Create(http://www.163.com/);
创建了这个对象后,就可以通过HttpWebRequest属性,设置很多HTTP标头字段的内容,如hwr.AddRange(100,1000);设置接收对象的范围为100-1000字节。
HttpWebReques对象使用GetResponse()方法时,会返回一个HttpWebResponse对象,为提出HTTP返回报文信息,需要使用HttpWebResponse的GetResponseStream()方法,该方法返回一个Stream对象,可以读取HTTP返回的报文,如:首先定义一个Strean 对象 public System.IO.Stream ns; 然后 ns=hwr.GetResponse ().GetResponseStream ();即可创建Stream对象。有了以上的准备知识后下面开始设计我们的多线程互联网文件的下载程序,首先打开.Net集成开发环境,选择“文件”、“新建”、“项目”,然后选择“Visual C#项目”,在向导右边列表框中选中“Windows应用程序”,输入项目名称,如本例为:httpftp,然后选择“确定”按钮,向导自动生成了一个 Windows应用程序项目。首先打开窗口设计器设计应用程序窗口,增加如下控件:
一个列表框 listBox1 三个文本标签 label1-label3 三个文本框 textBox1-textBox3 一个开始接收按钮 button1 设计好的窗口如下图:
控件定义代码是:
- public System.Windows.Forms.ListBox listBox1;
- private System.Windows.Forms.Label label1;
- private System.Windows.Forms.TextBox textBox1
- private System.Windows.Forms.Button button1;
- private System.Windows.Forms.Label label2;
- private System.Windows.Forms.TextBox textBox2;
- private System.Windows.Forms.Label label3;
- private System.Windows.Forms.TextBox textBox3;
- private System.Windows.Forms.Label label4;
- private System.Windows.Forms.TextBox textBox4;
打开Form1的代码编辑器,增加如下的命名空间:
- using System.Net;//网络功能
- using System.IO;//流支持
- using System.Threading ;//线程支持
增加如下的程序变量:
- public bool[] threadw; //每个线程结束标志
- public string[] filenamew;//每个线程接收文件的文件名
- public int[] filestartw;//每个线程接收文件的起始位置
- public int[] filesizew;//每个线程接收文件的大小
- public string strurl;//接受文件的URL
- public bool hb;//文件合并标志
- public int thread;//进程数
定义一个HttpFile类,用于管理接收线程,其代码如下:
- public class HttpFile
- {
- public Form1 formm;
- public int threadh;//线程代号
- public string filename;//文件名
- public string strUrl;//接收文件的URL
- public FileStream fs;
- public HttpWebRequest request;
- public System.IO.Stream ns;
- public byte[] nbytes;//接收缓冲区
- public int nreadsize;//接收字节数
- public HttpFile(Form1 form,int thread)//构造方法
- {
- formm=form;
- threadh=thread;
- }
- ~HttpFile()//析构方法
- {
- formm.Dispose ();
- }
- public void receive()//接收线程
- {
- filename=formm.filenamew[threadh];
- strUrl=formm.strurl;
- ns=null;
- nbytes= new byte[512];
- nreadsize=0;
- formm.listBox1 .Items .Add ("线程"+threadh.ToString ()+"开始接收");
- fs=new FileStream (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 (Exception er)
- {
- MessageBox.Show (er.Message );
- fs.Close();
- }
- formm.listBox1 .Items.Add ("进程"+threadh.ToString ()+"接收完毕!");
- formm.threadw[threadh]=true;
- }
- }
该类和Form1类处于统一命名空间,但不包含在Form1类中。下面定义“开始接收”按钮控件的事件响应函数:
- private void button1_Click(object sender, System.EventArgs e)
- {
- DateTime dt=DateTime.Now;//开始接收时间
- textBox1.Text =dt.ToString ();
- strurl=textBox2.Text .Trim ().ToString ();
- HttpWebRequest request;
- long filesize=0;
- try
- {
- request=(HttpWebRequest)HttpWebRequest.Create (strurl);
- filesize=request.GetResponse ().ContentLength;//取得目标文件的长度
- request.Abort ();
- }
- catch (Exception er)
- {
- MessageBox.Show (er.Message );
- }
- // 接收线程数
- thread=Convert.ToInt32 (textBox4.Text .Trim().ToString (),10);
- //根据线程数初始化数组
- threadw=new bool [thread];
- filenamew=new string [thread];
- filestartw=new int [thread];
- filesizew=new int[thread];
- //计算每个线程应该接收文件的大小
- int filethread=(int)filesize/thread;//平均分配
- int filethreade=filethread+(int)filesize%thread;//剩余部分由最后一个线程完成
- //为数组赋值
- for (int i=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=new Thread [thread];
- HttpFile[] httpfile=new HttpFile [thread];
- for (int j=0;j< thread;j++)
- {
- httpfile[j]=new HttpFile(this,j);
- threadk[j]=new Thread(new ThreadStart (httpfile[j].receive ));
- threadk[j].Start ();
- }
- //启动合并各线程接收的文件线程
- Thread hbth=new Thread (new ThreadStart (hbfile));
- hbth.Start ();
- }
合并文件的线程hbfile定义在Form1类中,定义如下:
- public void hbfile()
- {
- while (true)//等待
- {
- hb=true;
- for (int i=0;i< thread;i++)
- {
- if (threadw[i]==false)//有未结束线程,等待
- {
- hb=false;
- Thread.Sleep (100);
- break;
- }
- }
- if (hb==true)//所有线程均已结束,停止等待,
- {
- break;
- }
- }
- FileStream fs;//开始合并
- FileStream fstemp;
- int readfile;
- byte[] bytes=new byte[512];
- fs=new FileStream (textBox3.Text .Trim ().ToString (),System.IO.FileMode.Create);
- for (int k=0;k< thread;k++)
- {
- fstemp=new FileStream (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 ();
- DateTime dt=DateTime.Now;
- textBox1.Text =dt.ToString ();//结束时间
- MessageBox.Show ("接收完毕!!!");
- }
至此,一个多线程下载文件的程序就大功告成了,注意在输入本地文件名时,应按如下格式输入:“c:\\test\\httpftp\\bin\\d.htm”,因”\”后的字符在C#中是转义字符,线程数并非越大越好,一般5个线程就可以了,该程序在Visual Studio.Net 2002开发环境及Windows xp 上通过。
=========================================================
本文为转载,转载必须确保本文完整并完整保留原作者信息和本文链接
E-mail: khler@163.com
QQ: 23381103
MSN: pragmac@hotmail.com
原文:http://developer.51cto.com/art/200908/147018.htm
申明:转载只为传播知识,让更多人享受作者智慧的结晶!
如原作者对转载于此有异议,请立即联系本人,本人将在
第一时间删除,并深表歉意!
=========================================================
转载于:https://www.cnblogs.com/khler/archive/2009/10/16/1584313.html
C#实现HTTP协议:多线程文件传输相关推荐
- 基于FTP协议的文件传输与下载
目录 一.FTP协议: 二.文件上传: 1.连接服务器 2.登录操作 3.上传操作 三.文件下载 1.连接服务器 2.登录操作 3.下载操作 四. 总结: 一.FTP协议: ftp是(File Tra ...
- 【ASP.net文档】用C#实现HTTP协议下的多线程文件传输
很多人都有过使用网络蚂蚁或网络快车软件下载互联网文件的经历,这些软件的使用可以大大加速互联网上文件的传输速度,减少文件传输的时间.这些软件为什么有如此大的魔力呢?其主要原因是这些软件都采用了多线程下载 ...
- 教你写一个ftp协议(文件传输协议)
一.FTP协议简介 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制文件的双向传输.同时,它 ...
- 互联网协议 — FTP 文件传输协议
目录 文章目录 目录 FTP vsftpd 自动模式和被动模式 PORT 主动模式 PASV 被动模式 访问控制方式 部署配置 FTP Server Global config Anonymous U ...
- linux tcp文件分包_在Linux下基于TCP协议的文件传输程序.
[设计目的] 通过 Linux C 编程,设计一个基于 TCP/IP 的文件传输系统,实现网络文件的收发 [设计环境] Ubuntu 12.04 [设计方案] ( 1 )文件读写 任意文件都可以二进制 ...
- FTP协议(文件传输协议)
FTP是FileTransferProtocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制文件的双向传输.同时,它也是一个应用程序(Appl ...
- p2p服务器的协议,P2P文件传输协议之BitTorrent协议
BitTorrent协议是支持网络当中数据的上下传输的一个P2P文件传输协议.那么基于这个协议的BT软件大家肯定更不会陌生.但是它却有着更为广泛的使用,尤其是在一些大型网络数据交换平台中,也常常会使用 ...
- 内网安全-隧道技术-防火墙限制协议绕过-文件传输
隧道技术: 一种通过使用互联网络基础设施在网络之间传递数据的方式,包括数据封装. 传输和解包在内的全过程.使用隧道传递的数据(或负载)可以是不同协议的数据帧或包. 封装: 隧道协议将这些其他协议的数据 ...
- Socket 实现非阻塞式多线程文件传输(jpg mov 等各种格式)
Socket 基础 非阻塞式TCP socket 实现文件传输, 实测 传输5M的jpg , 30M的 NEF(单反原图) 以及 1G以上的mov文件,均正常接收 客户端可多开,服务器多线程实现服务器 ...
最新文章
- Citrix 服务器虚拟化之二十八 XenApp6.5发布文档内容
- Struts2封装获取表单数据方式
- 针对不同创业阶段的创业者适合参加哪些创业赛事活动呢?创业是一场异常艰辛的马拉松,坚持是唯一的捷径,借...
- 计算机科学基础知识(四): 动态库和位置无关代码
- ar android app,RakugakiAR安卓版
- Mybatis(13)动态sql语句if/where/foreach
- ​图片流量节省60%:基于CDN的sharpP自适应图片技术实践
- Java9的GI垃圾回收器
- POJ 2406 Power Strings
- linux内核编程4部曲之一:linux内核编译(2.6.12版本)图文解说
- 计算机应用 课件 .doc,《计算机应用基础》课件36915.doc
- 数据结构期末考试试题及答案
- Google可能将退出中国市场
- python语言是不是多模型语言_Python模型转换为Modelica模型的方法与流程
- DDOS攻击已然渗透互联网和物联网
- LTspice基础教程-033.绘制电容阻抗特性曲线
- 批量提取PPT里面包含的图片教程
- Oralce数据库断电之ORA-00600: 内部错误代码, 参数: [kcratr_nab_less_than_odr], [1], [37]
- C语言中的随机数 srand ( ) 和 rand ( )
- 5-40 奥运排行榜 (25分)
热门文章
- Linux shell 中获取当前目录的方法
- getset原子性 redis_Redis 分布式锁进化史解读 + 缺陷分析
- el-amap 第一次正常第二次报错_flutter run: build tools revision 报错解决
- mysql clean up_svn之clean up操作
- nginx upstream配置_Prometheus快速监控Nginx
- python提取txt中指定内容_提取视频中的音频——python三行程序搞定!
- Hive将查询结果保存到另一张表中
- 5行Python实现验证码识别,太稳了!
- 花木兰到底好看不,我用Python爬取了几万条评论!
- 我用 Python 帮朋友做了张图,结果