Mina处于中间层,它不关心底层网络数据如何传输,只负责接收底层数据,过滤并转换为Java对象提供给我们的应用程序,然后把应用程序响应值过滤并转换为底层识别的字节,提供给底层传输;
------总之:Mina是底层数据传输和用户应用程序交互的接口!
这个流程图不仅很直观的看出了Mina的工作流程,也涵盖了Mina的三个核心接口:IoService接口,IoFilter接口和IoHandler接口:
第一步. 创建服务对象(客户端或服务端) ---IoService接口实现
第二步. 数据过滤(编码解码等) ---IOFilter接口实现
第三步. 业务处理 ---IoHandler接口实现
Mina的精髓是IOFilter,它可以进行日志记录,信息过滤,编码解码等操作,把数据接收发送从业务层独立出来。
创建服务对象,则是把NIO繁琐的部分进行封装,提供简洁的接口。
业务处理是我们最关心的部分,跟普通的应用程序没任何分别。
package web.sample; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; //负责处理连接上来的客户机,即消息处理器 public class MinaServerHandler extends IoHandlerAdapter{ //客户端发送的消息到达时 @Override public void messageReceived(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub String s = (String)message; System.out.println("来自客户端的消息:"+s); session.write(s); } //一个客户端关闭时 @Override public void sessionClosed(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("one Client Disconnect"); } //一个客户端接入时 @Override public void sessionCreated(IoSession session) throws Exception { // TODO Auto-generated method stub System.out.println("one Client Connection"); } }
package web.sample; import java.io.IOException; import java.net.InetSocketAddress; import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.SocketAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class StartServer { public static void main(String[] args) { // 创建一个非阻塞的serever端socket,用Nio SocketAcceptor acceptor = new NioSocketAcceptor(); // 创建接收数据的过滤器 DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); // 设定这个过滤器规则(将一行一行读取数据) chain.addLast("myChin", new ProtocolCodecFilter(new TextLineCodecFactory())); // 设定服务器端的消息处理器:一个MinaServerHandler对象 acceptor.setHandler(new MinaServerHandler()); // 服务器端绑定的端口 int bindPort = 10000; // 绑定端口,启动服务器 try { acceptor.bind(new InetSocketAddress(bindPort)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Mina server is listing on:=" + bindPort); } }
1、使用telnet命令来和服务器进行连接,并发送消息,如图所示:
2、使用程序和服务器连接
package web.sample; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.util.logging.Logger; /* * 使用Socket创建客户端请求 */ public class EchoClient01 { // private Logger logger = Logger.getLogger(EchoClient01.class); private String HOST = "localhost"; private int PORT = 10000; private Socket socket; public EchoClient01() throws IOException { socket = new Socket(HOST, PORT); } public void talk() throws IOException { try { // 获得服务端响应信息的输入流 InputStream socketIn = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(socketIn)); // 给服务端发送信息的输出流 OutputStream socketOut = socket.getOutputStream(); PrintWriter pw = new PrintWriter(socketOut, true); BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in)); String msg = null; while ((msg = localReader.readLine()) != null) { pw.println(msg); // logger.info(br.readLine()); if (msg.equals("bye")) break; } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String args[]) throws IOException { new EchoClient01().talk(); } }
备注:public PrintWriter(OutputStream out,boolean autoFlush),通过现有的 OutputStream 创建新的 PrintWriter。此便捷构造方法创建必要的中间 OutputStreamWriter,后者使用默认字符编码将字符转换为字节。
如果只是创建使用这个PrintWriter(OutputStream out)构造方法,则服务器端是收到接收的信息的。