NIO的思路是基于多路选择的,即由原来的每个连接都由一个线程来等待消息,改为每个连接都在选择器上注册,由选择器来等待。当然NIO引入了很多新的概念,如Channel,Buffer、Charset、Selector等,使得编程更简洁、更面向对象化。

下面贴出用NIO API改造成UDP示例代码,注意其中使用Charset来编码解码的过程(当然Charset还支持很多其他编码不仅局限于默认编码)以及Buffer的使用。

package sinpo.usagedemo; 

import java.net.DatagramSocket; 
import java.net.InetSocketAddress; 
import java.net.SocketAddress; 
import java.nio.ByteBuffer; 
import java.nio.CharBuffer; 
import java.nio.channels.DatagramChannel; 
import java.nio.channels.SelectionKey; 
import java.nio.channels.Selector; 
import java.nio.charset.Charset; 
import java.util.Iterator; 
import java.util.Set; 


public class UDPServer extends Thread { 
public void run () { 
Selector selector = null ; 
try { 
DatagramChannel channel = DatagramChannel.open () ; 
DatagramSocket socket = channel.socket () ; 
channel.configureBlocking ( false ) ; 
socket.bind ( new InetSocketAddress ( 5057 )) ; 

selector = Selector.open () ; 
channel.register ( selector, SelectionKey.OP_READ ) ; 
catch ( Exception e ) { 
e.printStackTrace () ; 
} 

ByteBuffer byteBuffer = ByteBuffer.allocate ( 65536 ) ; 
while ( true ) { 
try { 
int eventsCount = selector.select () ; 
if ( eventsCount > 0 ) { 
Set selectedKeys = selector.selectedKeys () ; 
Iterator iterator = selectedKeys.iterator () ; 
while ( iterator.hasNext ()) { 
SelectionKey sk = ( SelectionKey iterator.next () ; 
iterator.remove () ; 
if ( sk.isReadable ()) { 
DatagramChannel datagramChannel = ( DatagramChannel sk 
.channel () ; 
SocketAddress sa = datagramChannel 
.receive ( byteBuffer ) ; 
byteBuffer.flip () ; 

// 测试:通过将收到的ByteBuffer首先通过缺省的编码解码成CharBuffer 再输出 
CharBuffer charBuffer = Charset.defaultCharset () 
.decode ( byteBuffer ) ; 
System.out.println ( "receive message:" 
+ charBuffer.toString ()) ; 
byteBuffer.clear () ; 

String echo = "This is the reply message from 服务器。" ; 
ByteBuffer buffer = Charset.defaultCharset () 
.encode ( echo ) ; 
datagramChannel.write ( buffer ) ; 
} 
} 
} 
catch ( Exception e ) { 
e.printStackTrace () ; 
} 
} 

} 

public static void main ( String [] args ) { 
new UDPServer () .start () ; 
} 
}

Client 

package  sinpo.usagedemo; 

import  java.net.InetSocketAddress; 
import  java.net.SocketAddress; 
import  java.nio.ByteBuffer; 
import  java.nio.channels.DatagramChannel; 
import  java.nio.channels.SelectionKey; 
import  java.nio.channels.Selector; 
import  java.nio.charset.Charset; 
import  java.util.Iterator; 
import  java.util.Set; 


public class  UDPClient  extends  Thread  { 
     public  void  run () { 
         DatagramChannel channel =  null ; 
         Selector selector =  null ; 
         try  { 
             channel = DatagramChannel.open () ; 
             channel.configureBlocking ( false ) ; 
             SocketAddress sa =  new  InetSocketAddress ( "localhost"  5057 ) ; 
             channel.connect ( sa ) ; 
          catch  ( Exception e ) { 
             e.printStackTrace () ; 
         } 

         try  { 
             selector = Selector.open () ; 
             channel.register ( selector, SelectionKey.OP_READ ) ; 
             channel.write ( Charset.defaultCharset () .encode ( "Tell me your time" )) ; 
          catch  ( Exception e ) { 
             e.printStackTrace () ; 
         } 
         
         ByteBuffer byteBuffer = ByteBuffer.allocate ( 100 ) ; 
         while  ( true ) { 
             try  { 
                 int  eventsCount = selector.select () ; 
                 if  ( eventsCount >  0 ) { 
                     Set selectedKeys = selector.selectedKeys () ; 
                     Iterator iterator = selectedKeys.iterator () ; 
                     while  ( iterator.hasNext ()) { 
                         SelectionKey sk =  ( SelectionKey  iterator.next () ; 
                         iterator.remove () ; 
                         if  ( sk.isReadable ()) { 
                             DatagramChannel datagramChannel =  ( DatagramChannel  sk 
                                     .channel () ; 
                             datagramChannel.read ( byteBuffer ) ; 
                             byteBuffer.flip () ; 
                             
                             //TODO 将报文转化为RUDP消息并调用RUDP协议处理器来处理 
                             
                             System.out.println ( Charset.defaultCharset () .decode ( 
                                     byteBuffer ) .toString ()) ; 
                             byteBuffer.clear () ; 
                             datagramChannel.write ( Charset.defaultCharset () 
                                     .encode ( "Tell me your time" )) ; 
                         } 
                     } 
                 } 
              catch  ( Exception e ) { 
                 e.printStackTrace () ; 
             } 
         } 

     } 
}
转载地址:http://www.blogjava.net/sinpo/archive/2008/10/20/235553.html