动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
  
   .Net → 阅读文章

 使用基本类库

作者来源: 
阅读 1427 人次 , 2006-3-29 4:32:00 


为了更好地理解c#与c++的区别和解决问题方式的变化,我们先来看一个比较简单的例子。我们将创建一个读取文本文件的类,并在屏幕上显示其内容。我将把它做成多线程程序,以便在从磁盘上读取数据时还可以做其他的工作。

在c++中,我们可能会创建一个读文件的线程和另一个做其他工作的线程,这二个线程将各自独立地运行,但可能会需要对它们进行同步。在c#中,我们也可以完成同样的工作,由于.net框架提供了功能强大的异步i/o机制,在编写线程时,我们会节省不少的时间。

异步i/o支持是内置在clr中的,而且几乎与使用正常的i/o流类一样简单。在程序的开始,我们首先通知编译器,我们将在程序中使用许多名字空间中的对象:

usingsystem;
usingsystem.io;
usingsystem.text;

在程序中包含system,并不会自动地包含其所有的子名字空间,必须使用using关健字明确地包含每个子名字空间。我们在例子中会用到i/o流类,因此需要包含system.io名字空间,我们还需要system.text名字空间支持字节流的ascii编码。

由于.net架构为完成了大部分的工作,编写这一程序所需的步骤相当简单。我们将用到stream类的beginread方法,它提供异步i/o功能,将数据读入到一个缓冲区中,当缓冲区可以处理时调用相应的处理程序。

我们需要使用一个字节数组作为缓冲区和回叫方法的代理,并将这二者定义为驱动程序类的private成员变量。

publicclassasynchiotester
{
privatestreaminputstream;
privatebyte[]buffer;
privateasynccallbackmycallback;

inputstream是一个stream类型的变量,我们将对它调用beginread方法。代理与成员函数的指针非常相似。代理是c#的第一类元素。

当缓冲区被磁盘上的文件填满时,.net将调用被代理的方法对数据进行处理。在等待读取数据期间,我们可以让计算机完成其他的工作。(在本例中是将1个整型变量由1增加到50000,但在实际的应用程序中,我们可以让计算机与用户进行交互或作其他有意义的工作。)

本例中的代理被定义为asynccallback类型的过程,这是stream的beginread方法所需要的。system空间中asynccallback类型代理的定义如下所示:

publicdelegatevoidasynccallback(iasyncresultar);

这一代理可以是与任何返回void类型值、将iasyncresult界面作为参数的方法相关联的。在该方法被调用时,clr可以在运行时传递iasyncresult界面对象作为参数。我们需要如下所示的形式定义该方法:

voidoncompletedread(iasyncresultasyncresult)

然后在构造器中与代理连接起来:

asynchiotester()
{
???
mycallback=newasynccallback(this.oncompletedread);
}

上面的代码将代理的实例赋给成员变量mycallback。下面是全部程序的详细工作原理。在main函数中,创建了一个类的实例,并让它开始运行:

publicstaticvoidmain()
{
asynchiotestertheapp=newasynchiotester();
theapp.run();
}

new关健字能够启动构造器。在构造器中我们打开一个文件,并得到一个stream对象。然后在缓冲中分配空间并与回调机制联结起来。

asynchiotester()
{
inputstream=file.openread(@"c:\msdn\fromcpptocs.txt");
buffer=newbyte[buffer_size];
mycallback=newasynccallback(this.oncompletedread);
}

在run方法中,我们调用了beginread,它将以异步的方式读取文件。

inputstream.beginread(
buffer,//存放结果
0,//偏移量
buffer.length,//缓冲区中有多少字节
mycallback,//回调代理
null);//本地对象

这时,我们可以完成其他的工作。

for(longi=0;i<50000;i++)
{
if(i%1000==0)
{
console.writeline("i:{0}",i);
}
}

文件读取操作结束后,clr将调用回调方法。

voidoncompletedread(iasyncresultasyncresult)
{

在oncompletedread中要做的第一件事就是通过调用stream对象的endread方法找出读取了多少字节:

intbytesread=inputstream.endread(asyncresult);

对endread的调用将返回读取的字节数。如果返回的数字比0大,则将缓冲区转换为一个字符串,然后将它写到控制台上,然后再次调用beginread,开始另一次异步读的过程。

if(bytesread>0)
{
strings=encoding.ascii.getstring(buffer,0,bytesread);
console.writeline(s);
inputstream.beginread(buffer,0,buffer.length,
mycallback,null);
}

现在,在读取文件的过程中就可以作别的工作了(在本例中是从1数到50000),但我们可以在每次缓冲区满了时对读取的数据进行处理(在本例中是向控制台输出缓冲区中的数据)。有兴趣的读者可以点击此处下载完整的源代码。

异步i/o的管理完全是由clr提供的,这样,在网络上读取文件时,会更好些。

 

在网络上读取文件

在c++中,在网络上读取文件需要有相当的编程技巧,.net对此提供了广泛的支持。事实上,在网络上读取文件仅仅是基础类库中stream类的另一种应用。

首先,为了对tcp/ip端口(在本例中是65000)进行监听,我们需要创建一个tcplistener类的实例。

tcplistenertcplistener=newtcplistener(65000);

一旦创建后,就让它开始进行监听。

tcplistener.start();

现在就要等待客户连接的要求了。

socketsocketforclient=tcplistener.accept();

tcplistener对象的accept方法返回一个socket对象,accept是一个同步的方法,除非接收到一个连接请求它才会返回。如果连接成功,就可以开始向客户发送文件了。

if(socketforclient.connected)
{
???

接下来,我们需要创建一个networkstream类,将报路传递给constructor:

networkstreamnetworkstream=newnetworkstream(socketforclient);

然后创建一个streamwriter对象,只是这次不是在文件上而是在刚才创建的networkstream类上创建该对象:

system.io.streamwriterstreamwriter=
newsystem.io.streamwriter(networkstream);

当向该流写内容时,流就通过网络被传输给客户端。

 

客户端的创建

客户端软件就是一个tcpclient类的具体例子,tcpclient类代表连向主机的一个tcp/ip连接。

tcpclientsocketforserver;
socketforserver=newtcpclient("localhost",65000);

有了tcpclient对象后,我们就可以创建networkstream对象了,然后在其上创建streamreader类:

networkstreamnetworkstream=socketforserver.getstream();
system.io.streamreaderstreamreader=
newsystem.io.streamreader(networkstream);

现在,只要其中有数据就读取该流,并将结果输出到控制台上。

do
{
outputstring=streamreader.readline();

if(outputstring!=null)
{
console.writeline(outputstring);
}
}
while(outputstring!=null);

为了对这一段代码进行测试,可以创建如下一个测试用的文件:

thisislineone
thisislinetwo
thisislinethree
thisislinefour

这是来自服务器的输出:

output(server)
clientconnected
sendingthisislineone
sendingthisislinetwo
sendingthisislinethree
sendingthisislinefour
disconnectingfromclient...
exiting...

下面是来自客户端的输出:

thisislineone
thisislinetwo
thisislinethree
thisislinefour

 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:类型映射
· 下一篇:XML 的汇出与读取
· 程序
· 用Asp.net实现基于XML的留言簿之一
· 用ASP.NET(VB版)创建WINDOWS 2000 SERVER站点
· 用C#编写发手机中文短信息Windows服务
· 透过vs.net数据窗体向导看Ado.net


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077