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

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

构建代码

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

 

应用程序


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

 

如上图所示,该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)。

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

NioDatagramAcceptor acceptor = new NioDatagramAcceptor();
acceptor.setHandler(new MemoryMonitorHandler(this));

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

DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addLast("logger", new LoggingFilter());

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

DatagramSessionConfig dcfg = acceptor.getSessionConfig();
dcfg.setReuseAddress(true);acceptor.bind(new InetSocketAddress(PORT));

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

IoHandler实现

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

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

详细代码如下:

Session Created Event

@Override
public void sessionCreated(IoSession session) throws Exception {
     SocketAddress remoteAddress = session.getRemoteAddress();
     server.addClient(remoteAddress);
}

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

Message Received Event

 @Override
 public void messageReceived(IoSession session, Object message) throws Exception {
        if (message instanceof IoBuffer) {
            IoBuffer buffer = (IoBuffer) message;
            SocketAddress remoteAddress = session.getRemoteAddress();
            server.recvUpdate(remoteAddress, buffer.getLong());
        }
 }

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

Session Closed Event

@Override
public void sessionClosed(IoSession session) throws Exception {
    System.out.println("Session closed...");
    SocketAddress remoteAddress = session.getRemoteAddress();
    server.removeClient(remoteAddress);
}

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

 

Client端代码分析

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

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

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

connector = new NioDatagramConnector();
connector.setHandler( this );
ConnectFuture connFuture = connector.connect( new InetSocketAddress("localhost", MemoryMonitor.PORT ));

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

connFuture.addListener( new IoFutureListener(){
    public void operationComplete(IoFuture future) {
		ConnectFuture connFuture = (ConnectFuture)future;
		if( connFuture.isConnected() ){
			session = future.getSession();
			try {
				sendData();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			log.error("Not connected...exiting");
		}
	}
});

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

private void sendData() throws InterruptedException {
	for (int i = 0; i < 30; i++) {
		long free = Runtime.getRuntime().freeMemory();
		IoBuffer buffer = IoBuffer.allocate(8);
		buffer.putLong(free);
		buffer.flip();
		session.write(buffer);

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
			throw new InterruptedException(e.getMessage());
		}
	}
}

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

你可能感兴趣的:(apache,框架,socket,XP,Mina)