• Apache Mina实战


    Mina介绍

    Mina可以用于快速的开发基于网络通信的应用,特别是在开发手机端的游戏应用时,使用的较为普遍。本文简单介绍了一个用Mina搭建的一个简易讨论组,通过该应用可以对Mina的基本用法用途有个大致的了解。

    界面效果

    界面元素不多,使用了两个AWT组件。

    客户端1:

    image

    客户端2:

    image

    服务端日志:

    image

    核心代码

    服务端Handler

       1: /**
       2:  * <服务端消息Handler>
       3:  * 
       4:  * @author liping.action@gmail.com
       5:  * @version V1.0
       6:  */
       7: public class ServerMessageHandler extends IoHandlerAdapter {
       8:     private MsgQueue msgQueueReceived;
       9:     private MsgQueue msgQueueSent;
      10:     
      11:     public MsgQueue getMsgQueueReceived() {
      12:         return msgQueueReceived;
      13:     }
      14:  
      15:     public void setMsgQueueReceived(MsgQueue msgQueueReceived) {
      16:         this.msgQueueReceived = msgQueueReceived;
      17:     }
      18:  
      19:     public MsgQueue getMsgQueueSent() {
      20:         return msgQueueSent;
      21:     }
      22:  
      23:     public void setMsgQueueSent(MsgQueue msgQueueSent) {
      24:         this.msgQueueSent = msgQueueSent;
      25:     }
      26:  
      27:     static {
      28:         PropertyConfigurator.configure(ClassLoader
      29:                 .getSystemResource("log4j.properties"));
      30:     }
      31:     private static Logger logger = Logger.getLogger(ServerMessageHandler.class);
      32:  
      33:     @Override
      34:     public void exceptionCaught(IoSession session, Throwable cause)
      35:             throws Exception {
      36:         logger.error(cause.toString());
      37:     }
      38:  
      39:     @Override
      40:     public void messageReceived(IoSession session, Object message)
      41:             throws Exception {
      42:         Msg msg = (Msg) message;
      43:         logger.info("MSG:from=" + session.getRemoteAddress() + ",id="
      44:                 + msg.getId() + ",content=" + msg.getContent());
      45:         Collection<IoSession> sessions = session.getService()
      46:                 .getManagedSessions().values();
      47:         msg.setId(session.getRemoteAddress().toString());
      48:         for (IoSession ioSession : sessions) {
      49:             ioSession.write(msg);
      50:         }
      51:     }
      52:  
      53:     @Override
      54:     public void messageSent(IoSession session, Object message) throws Exception {
      55:         logger.info(Constant.MESSAGE_SENT);
      56:     }
      57:  
      58:     @Override
      59:     public void sessionClosed(IoSession session) throws Exception {
      60:         logger.info(Constant.SESSION_CLOSED);
      61:     }
      62:  
      63:     @Override
      64:     public void sessionCreated(IoSession session) throws Exception {
      65:         logger.info(Constant.SESSION_CREATED);
      66:     }
      67:  
      68:     @Override
      69:     public void sessionIdle(IoSession session, IdleStatus status)
      70:             throws Exception {
      71:         logger.info(Constant.SESSION_IDLE);
      72:     }
      73:  
      74:     @Override
      75:     public void sessionOpened(IoSession session) throws Exception {
      76:         logger.info(Constant.SESSION_OPENED);
      77:         logger.info("address : "
      78:                 + session.getRemoteAddress());
      79:     }
      80:  
      81: }

    客户端handler

       1: /**
       2:  * <客户端handler>
       3:  * 
       4:  * @author liping.action@gmail.com
       5:  * @version V1.0
       6:  */
       7: public class ClientMessageHanlder extends IoHandlerAdapter {
       8:     private static Logger logger = Logger.getLogger(ClientMessageHanlder.class);
       9:     private MsgModel msgModel;
      10:     
      11:     public MsgModel getMsgModel() {
      12:         return msgModel;
      13:     }
      14:  
      15:     public void setMsgModel(MsgModel msgModel) {
      16:         this.msgModel = msgModel;
      17:     }
      18:  
      19:     @Override
      20:     public void exceptionCaught(IoSession session, Throwable cause)
      21:             throws Exception {
      22:         super.exceptionCaught(session, cause);
      23:     }
      24:  
      25:     @Override
      26:     public void messageReceived(IoSession session, Object message)
      27:             throws Exception {
      28:         Msg msg = (Msg) message;
      29:         logger.info("msg:id=" + msg.getId() + ",content=" + msg.getContent());
      30:         msgModel.setMsg(msg);
      31:         msgModel.fireModelChange();//触发模型变更,通知观察者
      32:     }
      33:  
      34:     @Override
      35:     public void messageSent(IoSession session, Object message) throws Exception {
      36:         super.messageSent(session, message);
      37:     }
      38:  
      39:     @Override
      40:     public void sessionClosed(IoSession session) throws Exception {
      41:         super.sessionClosed(session);
      42:     }
      43:  
      44:     @Override
      45:     public void sessionCreated(IoSession session) throws Exception {
      46:         super.sessionCreated(session);
      47:     }
      48:  
      49:     @Override
      50:     public void sessionIdle(IoSession session, IdleStatus status)
      51:             throws Exception {
      52:         super.sessionIdle(session, status);
      53:     }
      54:  
      55:     @Override
      56:     public void sessionOpened(IoSession session) throws Exception {
      57:         Msg msg = new Msg(session.getRemoteAddress().toString(),
      58:                 session.getLocalAddress() + " " + DateUtil.getCurrentData() + " 进入了讨论组!");
      59:         session.write(msg);
      60:     }
      61: }

    服务端启动器:

       1: /**
       2:  * 服务端启动器
       3:  * 
       4:  */
       5: public class ServerLauncher {
       6:     static {
       7:         PropertyConfigurator.configure(ClassLoader
       8:                 .getSystemResource("log4j.properties"));
       9:     }
      10:     private static Logger logger = Logger.getLogger(ServerMessageHandler.class);
      11:  
      12:     public static void main(String[] args) {
      13:         // 创建一个非阻塞的server端Socket ,用NIO
      14:         SocketAcceptor acceptor = new NioSocketAcceptor();
      15:         // 创建接收数据的过滤器
      16:         DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
      17:         // 设定这个过滤器将以对象为单位读取数据
      18:         ProtocolCodecFilter filter = new ProtocolCodecFilter(
      19:                 new ObjectSerializationCodecFactory());
      20:         chain.addLast("objectFilter", filter);
      21:         // 设定服务器消息处理器
      22:         acceptor.setHandler(new ServerMessageHandler());
      23:         // 服务器绑定的端口
      24:         int bindPort = 9988;
      25:         // 绑定端口,启动服务器
      26:         try {
      27:             acceptor.bind(new InetSocketAddress(bindPort));
      28:         } catch (IOException e) {
      29:             logger.error(e.toString());
      30:         }
      31:         logger.info("Mina Server run done! on port:" + bindPort);
      32:     }
      33: }

    客户端启动器:

       1: /**
       2:  * 客户端启动器
       3:  * 
       4:  */
       5: public class ClientLauncher {
       6:     static {
       7:         PropertyConfigurator.configure(ClassLoader
       8:                 .getSystemResource("log4j.properties"));
       9:     }
      10:  
      11:     public static void main(String[] args) {
      12:         // 创建消息模型(被观察者)
      13:         MsgModel model = new MsgModel();
      14:         // 创建一个tcp/ip 连接
      15:         NioSocketConnector connector = new NioSocketConnector();
      16:         /*---------接收对象---------*/
      17:         // 创建接收数据的过滤器
      18:         DefaultIoFilterChainBuilder chain = connector.getFilterChain();
      19:         // 设定这个过滤器将以对象为单位读取数据
      20:         ProtocolCodecFilter filter = new ProtocolCodecFilter(
      21:                 new ObjectSerializationCodecFactory());
      22:         chain.addLast("objectFilter", filter);
      23:         ClientMessageHanlder hanlder = new ClientMessageHanlder();
      24:         hanlder.setMsgModel(model);
      25:         // 设定客户端端的消息处理器
      26:         connector.setHandler(hanlder);
      27:         // Set connect timeout.
      28:         connector.setConnectTimeoutCheckInterval(30);
      29:         // 连结到服务器:
      30:         final ConnectFuture cf = connector.connect(new InetSocketAddress(
      31:                 "127.0.0.1", 9988));
      32:         createComponent(model, cf);
      33:         cf.awaitUninterruptibly();
      34:         cf.getSession().getCloseFuture().awaitUninterruptibly();
      35:         connector.dispose();
      36:     }
      37:  
      38:     private static void createComponent(MsgModel model, final ConnectFuture cf) {
      39:         JFrame frame = new JFrame("Client");
      40:         frame.setLocation(450, 300);
      41:         final TextField textField = new TextField();
      42:  
      43:         textField.addKeyListener(new KeyListener() {
      44:             public void keyTyped(KeyEvent arg0) {
      45:             }
      46:  
      47:             public void keyReleased(KeyEvent arg0) {
      48:             }
      49:  
      50:             public void keyPressed(KeyEvent arg0) {
      51:                 if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
      52:                     String value = textField.getText();
      53:                     if (!value.equals("")) {
      54:                         Msg msg = new Msg("0002", value);
      55:                         cf.getSession().write(msg);
      56:                         textField.setText("");
      57:                     }
      58:                 }
      59:             }
      60:         });
      61:         // 自定义TextArea
      62:         CusTextArea textArea = new CusTextArea();
      63:         model.addObserver(textArea);
      64:         frame.setSize(300, 450);
      65:         frame.setResizable(false);
      66:         frame.setBackground(Color.white);
      67:         frame.add(textField, BorderLayout.SOUTH);
      68:         frame.add(textArea, BorderLayout.NORTH);
      69:         frame.pack();
      70:         frame.setVisible(true);
      71:         frame.addWindowListener(new CloseHandler(cf.getSession()));
      72:         textField.requestFocus();
      73:     }
      74: }

    结语

    该应用为一个简单的讨论组程序,可实现多人讨论,说白了是重复造轮子,但通过此应用可以对mima的用法及原理进行简单了解。程序还有其他代码没有贴上来,全部由三部分组成,服务端、客户端、公共组件。公共组件提供服务端、客户端公共使用的部分,如消息,消息队列,消息模型等。如需要程序源码,联系我的邮件获取。

    下载地址

  • 相关阅读:
    hdu 5053 the Sum of Cube
    [LeetCode] Word Pattern
    [LeetCode] Minimum Depth of Binary Tree
    [C++] std::vector
    [LeetCode] Count Binary Substrings
    [LeetCode] Degree of an Array
    [LeetCode] String to Integer (atoi)
    [LintCode] 比较字符串
    [LeetCode] Valid Parentheses
    [LeetCode] Perfect Number
  • 原文地址:https://www.cnblogs.com/leefreeman/p/3328073.html
Copyright © 2020-2023  润新知