This is apache-mina-2.0.4

来源:互联网 发布:网络传播概论新编 pdf 编辑:程序博客网 时间:2024/05/18 00:43

这是使用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中的ServerSocketIoAcceptor 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代表接收到的数据@Overridepublic void messageReceived(IoSession session, Object message) throws Exception {String str = message.toString(); //我们已设定了服务器解析消息的规则是一行一行读取,这里就可转为StringSystem.out.println("The message received from Client is [" + str + "]");}@Overridepublic 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;}@Overridepublic 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 ================================================================================================= */@Overridepublic 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端 */@Overridepublic 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

原创粉丝点击