This is apache-mina-2.0.4

这是使用Mina2编写的服务端主类MyServer.java


package com.mina.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

/**
 * 简单Mina Server示例
 * @see 非阻塞I/O是JDK5.0提供的API,意思是服务器不用像以前那样调用accept()方法,阻塞等待了
 * @see 开发一个Mina应用,简单的说:就是创建连结、设定过滤规则、编写自己的消息处理器这三步
 * @see Mina执行流程:进入IoService-->IoProcessor-->IoFilter-->IoHandler-->IoFilter-->IoProcessor-->IoService
 */
public class MyServer {
	public static void main(String[] args) throws IOException {
		//指定服务器端所绑定的端口
		int bindPort = 9876;
		
		//初始化服务端的TCP/IP的基于NIO的套接字
		//即创建非阻塞服务器端,类似于Java中的ServerSocket
		IoAcceptor acceptor = new NioSocketAcceptor();
		
		//调用IoSessionConfig设置读取数据的缓冲区大小、读写通道均在10秒内无任何操作就进入空闲状态
		acceptor.getSessionConfig().setReadBufferSize(2048);
		acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
		
		/**
		 * 定义拦截器:可以包括日志输出、黑名单过滤、数据的编码(write方向)与解码(read方向)等功能
		 *           其中数据的encode与decode是最为重要的,也是在使用Mina时最主要关注的地方
		 */
		
		//启用Mina的日志跟踪
		acceptor.getFilterChain().addLast("logger", new LoggingFilter());
		
		//这段代码要在acceptor.bind()方法之前前执行,因为绑定套接字之后,就不能再做这些准备工作了
		//这里所要传输的是以换行符为标识的数据,所以使用了Mina自带的换行符编解码器工厂
		//若不清楚操作系统或Telnet软件的换行符是什么,可以删掉new TextLineCodecFactory(*,*,*)的后两个参数
		//即new TextLineCodecFactory(Charset.forName("UTF-8")),此时使用的就是TextLineCodec内部的自动识别机制
		//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
		acceptor.getFilterChain().addLast("codec", 
			new ProtocolCodecFilter(new TextLineCodecFactory(
				Charset.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue())));
		
		/**
		 * 指定服务器端的消息处理器。它负责编写业务逻辑,即接收、发送数据的地方
		 */
		
		//把编写好的IoHandler注册到IoService。它也要在acceptor.bind()方法之前前执行
		acceptor.setHandler(new ServerHandler());
		
		//绑定端口,启动服务器
		//该接口中的void bind()方法用于监听端口、void unbind()方法用于解除对套接字的监听
		//这里与传统的Java中的ServerSocket不同的是:IoAcceptor可以多次调用bind()方法同时监听多个端口
		//或者在一个方法中传入多个SocketAddress参数,来监听多个端口
		acceptor.bind(new InetSocketAddress(bindPort));
		
		System.out.println("MinaServer is startup, and it`s listing on := " + bindPort);
	}
}


这是我们编写的服务端消息处理器ServerHandler.java


package com.mina.server;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

/**
 * 自定义的消息处理器,必须实现IoHandlerAdapter类 
 * @see IoHandlerAdapter:它定义的方法用于处理程序接收到的消息,并处理通信中的连结,断开,消息到达等事件
 * @see                   客户机和服务器端创建后,都有一个setHandler方法,就是要传入我们重写的该类的对象
 * @see                   其中各个方法在通信中会根据情况自动调用,类似于Swing事件中的调用机制
 */
public class ServerHandler extends IoHandlerAdapter {
	//这是IoHandlerAdapter类中最重要的一个方法。IoSession代表与对方机器的TCP/IP连接,Object代表接收到的数据
	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String str = message.toString(); //我们已设定了服务器解析消息的规则是一行一行读取,这里就可转为String
		System.out.println("The message received from Client is [" + str + "]");
	}
	
	@Override
	public void sessionOpened(IoSession session) throws Exception{
		System.out.println("InComing Client:" + session.getRemoteAddress());
	}
}

package com.mina.client;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

import org.apache.mina.core.service.IoConnector;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

/**
 * 简单的TCPClient
 * @see Mina中的Server端和Client端的执行流程是一样的,唯一不同的是IoService的Client端实现是IoConnector
 * @see 这里我们实现Mina中的TCPClient。运行MyClient时,会发现MyServer控制台输入如下语句
 * @see The message received from Client is [岂曰无衣..]
 * @see The message received from Client is [月照沟渠....]
 * @see 说明服务器端收到的是两条消息,因为我们所用的编解码器是以换行符判断数据是否读取完毕的
 */
public class MyClient {
	public static void main(String[] args) {
		//Create TCP/IP connector
		//NioSocketConnector功能类似于JDK中的Socket类,它也是非阻塞的读取数据
		IoConnector connector = new NioSocketConnector();

		connector.setConnectTimeoutMillis(3000);
		
		connector.getFilterChain().addLast("codec", 
			new ProtocolCodecFilter(new TextLineCodecFactory(
				Charset.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue())));
		
		//注册IoHandler,即指定客户器端的消息处理器
		connector.setHandler(new ClientHandler("岂曰无衣..\r\n月照沟渠...."));
		
		//连接到服务器
		//ConnectFuture connect(SocketAddress arg0,SocketAddress arg1)
		//该方法用于与Server端建立连接,第二个参数若不传递则使用本地的一个随机端口访问Server端
		//该方法是异步执行的,且可以同时连接多个服务端
		connector.connect(new InetSocketAddress("127.0.0.1", 9876));
		
		System.out.println("Mina Client is startup");
	}
}

package com.mina.client;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

public class ClientHandler extends IoHandlerAdapter {
	private final String values;
	
	public ClientHandler(String values){
		this.values = values;
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		System.out.println("sessionCreated is invoked....");
	}

	/**
	 * 发送消息
	 * @see =================================================================================================
	 * @see 客户端连接有两个事件:sessionCreated和sessionOpened
	 * @see sessionCreated是由IoProcessor线程触发的,sessionOpened跟在其后,是由业务线程触发的
	 * @see 由于Mina中的IoProcessor线程非常少,因此sessionCreated通常用于处理耗时短的操作
	 * @see 而将业务初始化等功能放在sessionOpened事件中,比如发送消息
	 * @see =================================================================================================
	 * @see 我们可以在sessionOpened()、messageReceived()中使用IoSession.write()方法发送消息
	 * @see 因为在这两个方法中,TCP连接都是打开的状态,只不过发送的时机不同
	 * @see sessionOpened()是在TCP连接建立之后,接收到数据之前发送
	 * @see messageReceived()是在接收到数据之后发送
	 * @see =================================================================================================
	 */
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		session.write(values); //写数据,该操作是异步的
	}

	/**
	 * 关于TCP连接的关闭
	 * @see 无论在客户端还是服务端,IoSession都用于表示底层的一个TCP连接
	 * @see 那么你会发现无论是Server端还是Client端的IoSession调用close()后,TCP连接虽然显示关闭,但主线程仍在运行,即JVM并未退出
	 * @see 这是因为IoSession的close()仅仅是关闭了TCP的连接通道,并没有关闭Server端和Client端的程序
	 * @see 此时需要调用IoService.dispose()停止Server端和Client端
	 */
	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		System.out.println("与" + session.getRemoteAddress() + "通信过程中出现错误:[" + cause.getMessage() + "]..连接即将关闭....");
		//关闭IoSession,该操作也是异步的....true表示立即关闭,false表示所有写操作都flush后关闭
		session.close(false);
		//IoSession.IoService getService()用于返回与当前会话对象关联的IoService实例
		session.getService().dispose();
	}
}




转载地址:http://blog.csdn.net/jadyer/article/details/7662829

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值