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