当前位置:首页 > Java技术 > 正文内容

Java网络服务器编程(NIO版)

canca17年前 (2008-11-22)Java技术509

转自:http://blog.csdn.net/DaiJiaLin/archive/2005/04/17/351764.aspx


Java 1.4开始提供的NIO API常用于开发高性能网络服务器,本文演示了如何用这个API开发一个TCP Echo Server

Java网络服务器编程一文演示了如何使用JavaSocket API编写一个简单的TCP Echo Server。其阻塞式IO的处理方式虽然简单,但每个客户端都需要一个单独的Thread来处理,当服务器需要同时处理大量客户端时,这种做法不再可行。使用NIO API可以让一个或有限的几个Thread同时处理连接到服务器上的所有客户端。(关于NIO API的一些介绍,可以在Java NIO API详解一文中找到。)

NIO API允许一个线程通过Selector对象同时监控多个SelectableChannel来处理多路IONIO应用程序一般按下图所示工作:

Figure 1

Figure 1 所示,Client一直在循环地进行select操作,每次select()返回以后,通过selectedKeys()可以得到需要处理的SelectableChannel并对其一一处理。

这样做虽然简单但也有个问题,当有不同类型的SelectableChannel需要做不同的IO处理时,在图中Client的代码就需要判断channel的类型然后再作相应的操作,这往往意味着一连串的if else。更糟糕的是,每增加一种新的channel,不但需要增加相应的处理代码,还需要对这一串if else进行维护。(在本文的这个例子中,我们有ServerSocketChannelSocketChannel这两种channel需要分别被处理。)

如果考虑将channel及其需要的IO处理进行封装,抽象出一个统一的接口,就可以解决这一问题。在Listing 1中的NioSession就是这个接口。

NioSessionchannel()方法返回其封装的SelectableChannel对象,interestOps()返回用于这个channel注册的interestOpsregistered()是当SelectableChannel被注册后调用的回调函数,通过这个回调函数,NioSession可以得到channel注册后的SelectionKeyprocess()函数则是NioSession接口的核心,这个方法抽象了封装的SelectableChannel所需的IO处理逻辑。

Listing 1:

public interface NioSession {

 

    public SelectableChannel channel();

   

    public int interestOps();

   

    public void registered(SelectionKey key);

   

    public void process();  

}

NioSession一起工作的是NioWorker这个类(Listing 2),它是NioSession的调用者,封装了一个Selector对象和Figure 1中循环select操作的逻辑。理解这个类可以帮助我们了解该如何使用NioSession这个接口。

NioWorker实现了Runnable接口,循环select操作的逻辑就在run()方法中。在NioWorker – NioSession这个框架中,NioSessionchannel注册的时候会被作为attachment送入register 函数,这样,在每次 select() 操作的循环中,对于 selectedKeys() 中的每一个 SelectionKey ,我们都可以通过 attachment 拿到其相对应的 NioSession 然后调用其 process() 方法。

每次select()循环还有一个任务,就是将通过add()方法加入到这个NioWorkerNioSession注册到Selector上。在Listing 2的代码中可以看出,NioSession中的channel()被取出并注册在Selector上,注册所需的interestOpsNioSession中取出,NioSession本身则作为attachment送入register()函数。注册成功后,NioSessionregistered()回调函数会被调用。

NioWorkeradd()方法的作用是将一个NioSession加入到该NioWorker中,并wakeup当前的select操作,这样在下一次的select()调用之前,这个NioSession会被注册。stop()方法则是让一个正在run()NioWorker停止。closeAllChannels()会关闭当前注册的所有channel,这个方法可在NioWorker不再使用时用来释放IO资源。

Listing 2:

public class NioWorker implements Runnable {

   

    public NioWorker(Selector sel) {

       _sel = sel;

       _added = new HashSet();

    }

   

   

扫描二维码推送至手机访问。

版权声明:本文由Ant.Master's Blog发布,如需转载请注明出处。

本文链接:https://iant.work/post/350.html

标签: Java技术
分享给朋友:

“Java网络服务器编程(NIO版)” 的相关文章

对象序列化与反序列化

    序列化,并不是JAVA独有的。因此,在这里我用比较通俗的话说了。序列化就是把一个对象转换成有规则的二进制流。而反序列化就是把有规则的二进制数据重整成一个对象。其好处不难看见:1.可以把一个对象保存在一个文件里。例如,下载软件。当您关闭了软件,下次再打开...

Socket与ServerSocket的问题

//服务器端:import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.ServerSock...

Java语言的反射机制

    由于项目的需要,在项目中要实现即插即用的方式,也就是说可以动态地加载包,不用设置CLASSPATH路径。当项目发布时,不可能要用户来设置环境变量吧!因此,就要用到JAVA的反射机制了。昨天,我是在研究JAVA的JNI技术。由于没有时间,所以过几天才写JNI。今天...

JAVA获得一个文件夹大小

在JAVA里没有现成的方法获取一个文件夹的大小,那么我们可以用递归的方法,获取文件夹的大小。    import  java.util.*;  import  java.io.*;  class  GetFileSi...

IM技术(1)

    做项目了,NetCL今天开工了,在这些日子里,我会将自己研究的内容写下来。做个记录,以下是我在网上搜到的。关于管理用户状态的解决方案,当然,我都有一个方案。不过对客户端的任务有点重吧,我方法是客户端从服务器端获到一个用户在线状态后,接着就与服务器无关了。好友离线...

字符,字节和编码

字符,字节和编码

转自:http://www.regexlab.com/zh/encoding.htm------------------------------------------------------------- 级别:中级 摘要:本文介绍了字符与编码的发展过程,相关概念的正确理解。举例说明了一些实际应...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。