baidus 发表于 2015-8-2 09:21:36

Apache Mina实战

Mina介绍
  Mina可以用于快速的开发基于网络通信的应用,特别是在开发手机端的游戏应用时,使用的较为普遍。本文简单介绍了一个用Mina搭建的一个简易讨论组,通过该应用可以对Mina的基本用法用途有个大致的了解。
界面效果
  界面元素不多,使用了两个AWT组件。
  客户端1:

  客户端2:

  服务端日志:

核心代码
  服务端Handler

   
   1: /**

   2:*

   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 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:*

   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的用法及原理进行简单了解。程序还有其他代码没有贴上来,全部由三部分组成,服务端、客户端、公共组件。公共组件提供服务端、客户端公共使用的部分,如消息,消息队列,消息模型等。如需要程序源码,联系我的邮件获取。
  下载地址
页: [1]
查看完整版本: Apache Mina实战