Java网络服务器编程(NIO版)
转自:http://blog.csdn.net/DaiJiaLin/archive/2005/04/17/351764.aspx
从Java 1.4开始提供的NIO API常用于开发高性能网络服务器,本文演示了如何用这个API开发一个TCP Echo Server。
Java网络服务器编程一文演示了如何使用Java的Socket API编写一个简单的TCP Echo Server。其阻塞式IO的处理方式虽然简单,但每个客户端都需要一个单独的Thread来处理,当服务器需要同时处理大量客户端时,这种做法不再可行。使用NIO API可以让一个或有限的几个Thread同时处理连接到服务器上的所有客户端。(关于NIO API的一些介绍,可以在Java NIO API详解一文中找到。)
NIO API允许一个线程通过Selector对象同时监控多个SelectableChannel来处理多路IO,NIO应用程序一般按下图所示工作:

Figure 1
如Figure 1 所示,Client一直在循环地进行select操作,每次select()返回以后,通过selectedKeys()可以得到需要处理的SelectableChannel并对其一一处理。
这样做虽然简单但也有个问题,当有不同类型的SelectableChannel需要做不同的IO处理时,在图中Client的代码就需要判断channel的类型然后再作相应的操作,这往往意味着一连串的if else。更糟糕的是,每增加一种新的channel,不但需要增加相应的处理代码,还需要对这一串if else进行维护。(在本文的这个例子中,我们有ServerSocketChannel和SocketChannel这两种channel需要分别被处理。)
如果考虑将channel及其需要的IO处理进行封装,抽象出一个统一的接口,就可以解决这一问题。在Listing 1中的NioSession就是这个接口。
NioSession的channel()方法返回其封装的SelectableChannel对象,interestOps()返回用于这个channel注册的interestOps。registered()是当SelectableChannel被注册后调用的回调函数,通过这个回调函数,NioSession可以得到channel注册后的SelectionKey。process()函数则是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这个框架中,NioSession在channel注册的时候会被作为attachment送入register
函数,这样,在每次
select()
操作的循环中,对于
selectedKeys()
中的每一个
SelectionKey
,我们都可以通过
attachment
拿到其相对应的
NioSession
然后调用其
process()
方法。
每次select()循环还有一个任务,就是将通过add()方法加入到这个NioWorker的NioSession注册到Selector上。在Listing 2的代码中可以看出,NioSession中的channel()被取出并注册在Selector上,注册所需的interestOps从NioSession中取出,NioSession本身则作为attachment送入register()函数。注册成功后,NioSession的registered()回调函数会被调用。 NioWorker的add()方法的作用是将一个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(); } 序列化,并不是JAVA独有的。因此,在这里我用比较通俗的话说了。序列化就是把一个对象转换成有规则的二进制流。而反序列化就是把有规则的二进制数据重整成一个对象。其好处不难看见:1.可以把一个对象...… 在JAVA里没有现成的方法获取一个文件夹的大小,那么我们可以用递归的方法,获取文件夹的大小。 import java.util.*; import java.io.*; class GetFileSi… JAVA过滤HTML中的所有标记。非常好用!! package canca.regex; import java.util.regex.Matcher;import java.util.regex.Pattern; public class HtmlFilter { priva… 转自:http://www.regexlab.com/zh/encoding.htm------------------------------------------------------------- 级别:中级 摘要:本文介绍了字符与编码的发展过程,相关概念的正确理解。举例说明了一些实际应… Java //C.java class A { public A() {  … 容器类可以大大提高编程效率和编程能力,在Java2中,所有的容器都由SUN公司的Joshua Bloch进行了重新设计,丰富了容器类库的功能。 Java2容器类类库的用途是“保存对象”,它分为两类: Collection----一组独立的元素,通常…
“Java网络服务器编程(NIO版)” 的相关文章
对象序列化与反序列化
JAVA获得一个文件夹大小
过滤网页HTML标记
字符,字节和编码
Java VS .Net
两种Java容器类List和Set分析
发表评论
![]()
