mina.net

Mina.NET
.NET implementation of [Apache MINA] (http://mina.apache.org/). I like the ideas in it, simple yet functional, but I failed to find one in .NET, finally I created one.

Mina.NET is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract event-driven asynchronous API over various transports such as TCP/IP via async socket.

Mina.NET is often called:

NIO framework library,
client server framework library, or
a networking socket library
Features
Mina.NET is a simple yet full-featured network application framework which provides:

Unified API for various transport types:
TCP/IP & UDP/IP via .NET asynchronous socket
Serial communication (RS232)
Loopback (in-application pipe) communication
You can implement your own!
Filter interface as an extension point;
Low-level and high-level API:
Low-level: uses IoBuffers
High-level: uses user-defined message objects and codecs
Highly customizable thread model:
Single thread
One thread pool
More than one thread pools
Out-of-the-box SSL · TLS
Overload shielding & traffic throttling
Stream-based I/O support via StreamIoHandler
Quick Start

  IoAcceptor acceptor = new AsyncSocketAcceptor();

  acceptor.FilterChain.AddLast("logger", new LoggingFilter());
  acceptor.FilterChain.AddLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Encoding.UTF8)));

  acceptor.ExceptionCaught += (o, e) => Console.WriteLine(e.Exception);
  
  acceptor.SessionIdle += (o, e) => Console.WriteLine("IDLE " + e.Session.GetIdleCount(e.IdleStatus));
  
  acceptor.MessageReceived += (o, e) =>
  {
    String str = e.Message.ToString();

    // "Quit" ? let's get out ...
    if (str.Trim().Equals("quit", StringComparison.OrdinalIgnoreCase))
    {
      e.Session.Close(true);
      return;
    }

    // Send the current date back to the client
    e.Session.Write(DateTime.Now.ToString());
    Console.WriteLine("Message written...");
  };
  
  acceptor.Bind(new IPEndPoint(IPAddress.Any, 8080));
See https://mina.codeplex.com/documentation for more.

License
Licensed under the Apache License, Version 2.0. You may obtain a copy of the License at [LICENSE] (LICENSE) or http://www.apache.org/licenses/LICENSE-2.0.

公司做的是电商,CTO打算把2.0系统用java 语言开发,LZ目前不打算做java,所以 选择离职。离职前,在公司负责的最后一个项目 供应链系统。

系统分为 3套子系统:

1 供应链工作平台(即用户操作平台):采用CS架构,Sqlite做缓存。

2 消息中心: 后台程序,采用mina.net,scoket 长连接 保证服务消息的 推送,后台消息的提醒,和 系统对最新订单的缓存。

3 WindowsService 监控消息中心,保证消息中心 随系统的开启而启动

mina 简介:

Apache Mina Server 是一个网络通信应用框架,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架,Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是Java NIO 作为底层支持)操作的编程模型。

mina.net 是Apache Mina Server 的.net 版本 主要用于系统的长连接通信

安装:

PM> Install-Package Mina

mina.net 主要对象:

1.AsyncSocketConnector: 发起链接

2.IoSession:mina 链接创建成功之后 客户端,服务的的数据传送

3.IoHandlerAdapter:适配器类。可以扩展

4.DemuxingProtocolCodecFactory:构建协议编码工厂

适配器主要方法:

1 MessageReceived:收到消息时触发

2.MessageSent 发送消息后触发

3.SessionClosed 关闭Session时 触发

4.SessionCreated 创建Session时 触发

5.ExceptionCaught 发生异常时 触发

6.SessionIdleSession 空闲时 触发

实现思路:

创建mina链接:

public void StartProcess(LoginContext config)
        {
AsyncSocketConnector connector = new Mina.Transport.Socket.AsyncSocketConnector();
//注册协议编解码器工厂
 connector.FilterChain.AddLast("encoding", new ProtocolCodecFilter(new MyMinaCodecFactory()));
//指定服务端IP 和端口号
            connector.DefaultRemoteEndPoint = new IPEndPoint(IPAddress.Parse(MinaConfig.Ip), MinaConfig.Port);
//初始化 消息处理类
            var headerDic = CreateHeader();
//继承IoHandlerAdapter构建适配器
            MinaMessageHandler headler = new MinaMessageHandler(config, connector, headerDic);
 
            connector.Handler = headler;
 
            while (true)
            {
                try
                {
                    //ClientHandler
                    //建立链接
                    session = connector.Connect().Await().Session;
                    break;
                }
                catch (Exception ex)
                {
                    _Log.Error(ex.Message, ex);
                    Thread.Sleep(1000);
                }
 
            }
}

链接建立成功之后,触发mina.net 内部机制的SessionCreated 方法,登录用户

public override void SessionCreated(Mina.Core.Session.IoSession session)
        {
            try
            {
                MyBaseMessage message = new LoginRequestMessage(ClientConfig.ClientAddr,ClientConfig.SharedSecret);
                (message as LoginRequestMessage).SetAutherString();
                session.Write(message);
            }
            catch (Exception ex)
            {
                _Log.Error(ex.Message, ex);
            }
            finally
            {
                base.SessionCreated(session);
            }
        }

重写MessageReceived方法,收到服务器消息之后,处理相应事件

/// <summary>
      /// 收到消息时 触发--处理消息,给服务器发送处理结果
      /// </summary>
      /// <param name="session"></param>
      /// <param name="message"></param>
      public override void MessageReceived(Mina.Core.Session.IoSession session, object message)
      {
          try
          {
              if (message is MyBaseMessage)
              {
                  var m = message as MyBaseMessage;
 
                  if (HeaderDic.Keys.Any(p=>p==m.GetCommandType()))
                  {
                      var messageHeader = HeaderDic[m.GetCommandType()];
 
                      messageHeader.Handle(session,m);
                  }
                   
              }
          }
          catch (Exception ex)
          {
              _Log.Error(ex.Message, ex);
          }
          finally
          {
              base.MessageReceived(session, message);
          }
           
      }

重写 SessionClosed 事件,关闭session时,通知服务器,客户端已关闭链接

/// <summary>
       /// 关闭Session时 触发-发送关闭消息
       /// </summary>
       /// <param name="session"></param>
       public override void SessionClosed(Mina.Core.Session.IoSession session)
       {
           try
           {
               while (true)
               {
                   try
                   {
                       if (Connector != null)
                       {
                           if (!Connector.Disposed)
                           {
                               session = Connector.Connect().Await().Session;
 
                               break;
                           }
                           else
                           {
                               break;
                           }
                       }
                   }
                   catch (Exception ex)
                   {
                       Thread.Sleep(1000);
                   }
               }
           }
           catch (Exception ex)
           {
               _Log.Error(ex.Message, ex);
           }
           finally
           {
               base.SessionClosed(session);
           }
       }

重写 ExceptionCaught 方法,发生异常时,关闭链接

/// <summary>
        /// 发生异常时 触发,关闭session 重新登录
        /// </summary>
        /// <param name="session"></param>
        /// <param name="cause"></param>
        public override void ExceptionCaught(Mina.Core.Session.IoSession session, Exception cause)
        {
            try
            {
                session.Close(true);
                _Log.Error(cause.Message, cause);
            }
            catch (Exception ex)
            {
                _Log.Error(ex.Message, ex);
            }
            finally
            {
                base.ExceptionCaught(session, cause);
            }
        }

重写 SessionIdle 方法,session空闲时,测试心跳

/// <summary>
       /// Session 空闲时 发生
       /// </summary>
       /// <param name="session"></param>
       /// <param name="status"></param>
       public override void SessionIdle(Mina.Core.Session.IoSession session, Mina.Core.Session.IdleStatus status)
       {
           try
           {
               MyBaseMessage message = new DetectionMessage();
 
               session.Write(message);
           }
           catch (Exception ex)
           {
               _Log.Error(ex.Message, ex);
           }
           finally
           {
               base.SessionIdle(session, status);
           }
       }

构建协议编解码器工厂

public class MyMinaCodecFactory : DemuxingProtocolCodecFactory
   {
       public MyMinaCodecFactory()
       {
           AddMessageEncoder(new MyMinaEncoder());
           AddMessageDecoder(new MyMinaDecoder());
       }
   }

编码器工厂,将对象 序列号成 bytes 数据

public class MyMinaEncoder : IMessageEncoder<MyBaseMessage>
   {
 
       public void Encode(IoSession session, MyBaseMessage message, IProtocolEncoderOutput output)
       {
           IoBuffer buf = IoBuffer.Allocate(12);
           buf.AutoExpand = true;
 
           var messageBytes = message.EncodeMessage();
 
           buf.Put(messageBytes);
           buf.Flip();
 
           session.Write(buf);
 
       }
 
       public void Encode(IoSession session, object message, IProtocolEncoderOutput output)
       {
           IoBuffer buf = IoBuffer.Allocate(12);
           buf.AutoExpand = true;
 
           if (message is MyBaseMessage)
           {
               var m = message as MyBaseMessage;
 
               var messageBytes = m.EncodeMessage();
 
               buf.Put(messageBytes);
               buf.Flip();
 
           }
           
           session.Write(buf);
 
       }
   }

解码器工厂,将字节转换为对象

public class MyMinaDecoder : IMessageDecoder
    {
        public ILog _Log = LogManager.GetLogger("MessageHandler");
 
        public MessageDecoderResult Decodable(IoSession session,IoBuffer input)
        {
            try
            {
                if (input.Remaining < CommandConfig.messageHeaderLength)
                {
                    return MessageDecoderResult.NeedData;
                }
                var headerBytes = new byte[CommandConfig.messageHeaderLength];
                for (int i = 0; i < CommandConfig.messageHeaderLength; i++)
                {
                    headerBytes[i] = input.Get(i);
                }
 
                var lengthBytes = new byte[4];
                var commandIdBytes = new byte[4];
                var sequenceBytes = new byte[4];
 
                Array.Copy(headerBytes, 0, lengthBytes, 0, 4);
                Array.Copy(headerBytes, 4, commandIdBytes, 0, 4);
                Array.Copy(headerBytes, 8, sequenceBytes, 0, 4);
 
 
                var messageLength = lengthBytes.ByteToUint();//Convert.ToInt32(Encoding.Default.GetString(headerBytes, 0, 4));
 
                var messageCommand = commandIdBytes.ByteToUint();//(uint)Convert.ToInt32(Encoding.Default.GetString(headerBytes, 4, 4));
 
                if (messageCommand==CommandConfig.connect
                    || messageCommand == CommandConfig.connectResp
                    || messageCommand == CommandConfig.terminate
                    || messageCommand == CommandConfig.terminateResp
                    || messageCommand == CommandConfig.notify
                    || messageCommand == CommandConfig.notifyResp
                    || messageCommand == CommandConfig.cmppActiveTest
                    || messageCommand == CommandConfig.cmppActiveTestResp)
                {
                    return MessageDecoderResult.OK;
                }
                return MessageDecoderResult.NotOK;
 
            }
            catch (Exception ex)
            {
                _Log.Error(ex.Message, ex);
                return MessageDecoderResult.NeedData;
            }
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是刘彦宏吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值