MINA2官方教程翻译(8)传输特性之UDP

该教程可以帮助你使用MINA框架编写基于UDP的Socket应用程序。在这篇教程中,我们将编写一个server端程序,server 可以通过连接该程序来展现client端程序的内存使用情况。现实中的很多程序都已经具备与该程序类似的功能,可以监控程序来内存使用情况。

构建代码

MINA 2.0的最终版本还没有release,但是你可以下载最新的版本。如果你希望从trunk构建代码,可以参考开发者指南。

 

应用程序


 

如上图所示,该server在端口18567监听,client端连接server端并向server端发送内存使用数据。在上图所展示应用中,共有两个client连接到了server。

 

程序执行流程

  1. server在18567端口监听客户端请求;
  2. client连接server端,server会在Session Created事件处理时增加一个Tab页;
  3. clients向server发送内存使用数据;
  4. server端把接收到的数据展现在Tab上。

Server端代码分析

我们可以在MINA的示例代的org.apache.mina.example.udp包下找到这些代码。对于每个实例,我们只需要关系MINA相关的代码。

要想构建该server,我们需要做如下操作:

  1. 创建一个数据报socket,监听client端请求。(请参考MemoryMonitor.java);
  2. 创建一个IoHandler来处理MINA框架生成的各种事件。(请参考MemoryMonitorHandler.java)。

第一步可以通过该程序片来实现:

Java代码  收藏代码
  1. NioDatagramAcceptor acceptor = new NioDatagramAcceptor();  
  2. acceptor.setHandler(new MemoryMonitorHandler(this));  

这里,我们创建一个NioDatagramAcceptor来监听client端请求,并且设置它的IoHandler。变量"PORT"是一个 int值。下一步我们家filter链中加入了一个logging filter。LoggingFilter是一个非常不错的记录日志的方式,它可以在很多节点处生成日志信息,这些热值能够展现出MINA框架的工作方 式。

Java代码  收藏代码
  1. DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();  
  2. chain.addLast("logger"new LoggingFilter());  

下一步我们深入一下UDP传输所特有的代码。我们设置acceptor可以重用address。

Java代码  收藏代码
  1. DatagramSessionConfig dcfg = acceptor.getSessionConfig();  
  2. dcfg.setReuseAddress(true);acceptor.bind(new InetSocketAddress(PORT));  

 当然,最后一件事情是调用bind()方法来绑定端口。

IoHandler实现

Server端主要关心如下三个事件:

  • Session创建
  • Message接收
  • Session关闭

详细代码如下:

Session Created Event

Java代码  收藏代码
  1. @Override  
  2. public void sessionCreated(IoSession session) throws Exception {  
  3.      SocketAddress remoteAddress = session.getRemoteAddress();  
  4.      server.addClient(remoteAddress);  
  5. }  

 在session创建事件中,我们调用addClient()方法来增加一个Tab页。

Message Received Event

Java代码  收藏代码
  1. @Override  
  2. public void messageReceived(IoSession session, Object message) throws Exception {  
  3.        if (message instanceof IoBuffer) {  
  4.            IoBuffer buffer = (IoBuffer) message;  
  5.            SocketAddress remoteAddress = session.getRemoteAddress();  
  6.            server.recvUpdate(remoteAddress, buffer.getLong());  
  7.        }  
  8. }  

 在message接收事件中,我们从接收到的消息中得到所关心的内存使用的数据;应用程序还需要发送响应信息。在这个方法中,处理消息和发送响应都是通过session完成的。

Session Closed Event

Java代码  收藏代码
  1. @Override  
  2. public void sessionClosed(IoSession session) throws Exception {  
  3.     System.out.println("Session closed...");  
  4.     SocketAddress remoteAddress = session.getRemoteAddress();  
  5.     server.removeClient(remoteAddress);  
  6. }  

在session关闭事件中,我们需要删除对应的Tab页。

 

Client端代码分析

在这一节,我们将解释一下客户端代码。实现客户端我们需要进行如下操作:

  • 创建Socket并连接到server端
  • 设置IoHandler
  • 收集内存使用信息
  • 发送数据到server端

我们从MemMonClient.java开始,可以在org.apache.mina.example.udp.client包下找到它。开始的几行代码非常简单:

Java代码  收藏代码
  1. connector = new NioDatagramConnector();  
  2. connector.setHandler( this );  
  3. ConnectFuture connFuture = connector.connect( new InetSocketAddress("localhost", MemoryMonitor.PORT ));  

 这里我们创建了一个NioDatagramConnector,设置了它的handler并且连接到server端。我们必须在 InetSocketAddress对象中设定host,否则程序不能正常运行。该程序是在Windows XP环境下开发运行的,所以与其他环境可能存在差别。下一步我们等待确认client已经连接到server端,一旦连接建立,我们可以开始向 server端发送数据。代码如下:

Java代码  收藏代码
  1. connFuture.addListener( new IoFutureListener(){  
  2.     public void operationComplete(IoFuture future) {  
  3.         ConnectFuture connFuture = (ConnectFuture)future;  
  4.         if( connFuture.isConnected() ){  
  5.             session = future.getSession();  
  6.             try {  
  7.                 sendData();  
  8.             } catch (InterruptedException e) {  
  9.                 e.printStackTrace();  
  10.             }  
  11.         } else {  
  12.             log.error("Not connected...exiting");  
  13.         }  
  14.     }  
  15. });  

这里我们在ConnectFuture对象中加入一个listener,当client连接到server端时,operationComplete方法将被回调,这时我们开始发送数据。我们通过调用sendData方法向server端发送数据,该方法如下:

Java代码  收藏代码
  1. private void sendData() throws InterruptedException {  
  2.     for (int i = 0; i < 30; i++) {  
  3.         long free = Runtime.getRuntime().freeMemory();  
  4.         IoBuffer buffer = IoBuffer.allocate(8);  
  5.         buffer.putLong(free);  
  6.         buffer.flip();  
  7.         session.write(buffer);  
  8.   
  9.         try {  
  10.             Thread.sleep(1000);  
  11.         } catch (InterruptedException e) {  
  12.             e.printStackTrace();  
  13.             throw new InterruptedException(e.getMessage());  
  14.         }  
  15.     }  
  16. }  

 该方法会在30秒内每秒向server端发送当前的剩余内存Cincinnati。你可以看到我们分配了一个足够大的IoBuffer来装载一个long型的变量。最后这个buffer被flipped并发送至server端。

来源://作者:/更新时间:2013-03-29
相关文章
评论:
验证码:
匿名评论:

最新文章

文章排行