dotnetty 整合 msgpack编解码框架

dotnetty 整合 msgpack编解码框架


主要是作java开发的,这一段时间用到了netty,权衡之下编解码框架选择了messagepack,当然protobuf同样是是很好的一种编解码框架,只是项目中需要传对象需要支持byte[]形式,而protobuf并不支持,经过努力也只能封装出支持list的数据结构,能力有限,就选择了messagepack。
对于java方面的用法就不多说了,资料有很多,尤其推荐《netty权威指南》。
废话不多说了,直接说C#的开发了,在网上似乎没有完整的整合资料,就贴出来,和大家分享以下。不过本人并非专业的C#开发,又不完善或不恰当之处,望理解并告知。

  1. dotnetty的安装
    DotNetty是开源的,它的源代码托管在Github上:
    https://github.com/azure/dotnetty
    源码内配有多个不同种类的案例,读完对于dotnetty的入门应该足够了

    对于我这个C#的外行,对于C#的导包感觉很新鲜,在这里说一下:
    步骤如下:
    ①:新建一个C#项目
    ②:https://www.nuget.org/downloads 下载并安装完成
    ③:在工具->Nuget包管理器->程序包管理器控制台依次输入
            Install-Package DotNetty.Common -Version 0.4.6
            Install-Package DotNetty.Transport -Version 0.4.6
            Install-Package DotNetty.Codecs -Version 0.4.6
            Install-Package DotNetty.Handlers -Version 0.4.6
            依赖添加完毕

  2. messagepack的安装
    对于c#开发来说,想要运用messagepack在网上的援助同样很少,大概最先搜索到的都是这一篇:
    https://www.cnblogs.com/Leo_wl/p/8143259.html
    不过这一篇博客,写的很详细,包括对messagepack与其他编解码框架的性能对比分析、依赖导入方法,以及基础的应用,希望各位去看一下,这里就不做再做摘录了。

  3. 整合dotnettymsgpack编解码框架
    完成前两个步骤就可以进行dotnetty+msgpack开发了,就不多说了,直接贴代码:

 class MsgPackEcode : MessageToByteEncoder
    {
        protected override void Encode(IChannelHandlerContext context, object message, IByteBuffer output)
        {

            byte [] temp = MessagePackSerializer.Serialize(message);        
            output.WriteBytes(temp);
        }
    }
    class MsgPackDecode : MessageToMessageDecoder
    {
        protected override void Decode(IChannelHandlerContext context, IByteBuffer message, List<object> output)
        {
            byte[] array;
            int length = message.ReadableBytes;
            array = new byte[length];
            message.GetBytes(message.ReaderIndex, array, 0, length);

            output.Add(MessagePackSerializer.Deserialize(array));
        }
    } 
  
服务端
    namespace Echo.Server
{
    using System;
    using System.Threading.Tasks;
    using DotNetty.Codecs;
    using DotNetty.Handlers.Logging;
    using DotNetty.Transport.Bootstrapping;
    using DotNetty.Transport.Channels;
    using DotNetty.Transport.Channels.Sockets;
    using MsgPack;

    class EchoServer
    {
        static async Task RunServerAsync()
        {


            IEventLoopGroup bossGroup;
            IEventLoopGroup workerGroup;


            bossGroup = new MultithreadEventLoopGroup(1);
            workerGroup = new MultithreadEventLoopGroup();



            try
            {
                var bootstrap = new ServerBootstrap();
                bootstrap.Group(bossGroup, workerGroup);


                bootstrap.Channel();


                bootstrap
                    .Option(ChannelOption.SoBacklog, 100)
                    .Handler(new LoggingHandler("SRV-LSTN"))
                    .ChildHandler(new ActionChannelInitializer(channel =>
                    {
                        IChannelPipeline pipeline = channel.Pipeline;


                        pipeline.AddLast("framing-enc", new LengthFieldPrepender(2));
                        pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2));
                        pipeline.AddLast("decoder", new MsgPackDecode());
                        pipeline.AddLast("ecoder", new MsgPackEcode());
                        pipeline.AddLast("echo", new EchoServerHandler());
                    }));

                IChannel boundChannel = await bootstrap.BindAsync(9090);

                Console.ReadLine();

                await boundChannel.CloseAsync();
            }
            finally
            {
                await Task.WhenAll(
                    bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)),
                    workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)));
            }
        }

        static void Main() => RunServerAsync().Wait();
    }
}
namespace Echo.Server
{
    using System;
    using System.Text;
    using DotNetty.Buffers;
    using DotNetty.Transport.Channels;

    public class EchoServerHandler : ChannelHandlerAdapter
    {
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            var buffer = message as IByteBuffer;
            if (buffer != null)
            {
                Console.WriteLine("Received from client: " + buffer.ToString(Encoding.UTF8));
            }
            context.WriteAsync(message);
        }

        public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Console.WriteLine("Exception: " + exception);
            context.CloseAsync();
        }
    }
}
客户端
namespace Echo.Client
{
    using System;

    using System.Threading.Tasks;
    using DotNetty.Codecs;
    using DotNetty.Transport.Bootstrapping;
    using DotNetty.Transport.Channels;
    using DotNetty.Transport.Channels.Sockets;
    using MsgPack;

    class EchoClient
    {
        static async Task RunClientAsync()
        {

            var group = new MultithreadEventLoopGroup();

            try
            {
                var bootstrap = new Bootstrap();
                bootstrap
                    .Group(group)
                    .Channel()
                    .Option(ChannelOption.TcpNodelay, true)
                    .Handler(new ActionChannelInitializer(channel =>
                    {
                        IChannelPipeline pipeline = channel.Pipeline;



                        pipeline.AddLast("framing-enc", new LengthFieldPrepender(2));
                        pipeline.AddLast("framing-dec", new LengthFieldBasedFrameDecoder(ushort.MaxValue, 0, 2, 0, 2));
                        pipeline.AddLast("decoder", new MsgPackDecode());
                        pipeline.AddLast("ecoder", new MsgPackEcode());

                        pipeline.AddLast("echo", new EchoClientHandler());
                    }));

                IChannel clientChannel = await bootstrap.ConnectAsync("127.0.0.1",9090);

                Console.ReadLine();

                await clientChannel.CloseAsync();
            }
            finally
            {
                await group.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1));
            }
        }
        static void Main() => RunClientAsync().Wait();
    }
}
namespace Echo.Client
{
    using System;
    using System.Text;
    using DotNetty.Buffers;
    using DotNetty.Transport.Channels;


    public class EchoClientHandler : ChannelHandlerAdapter
    {
        readonly IByteBuffer initialMessage;

        public EchoClientHandler()
        {
            this.initialMessage = Unpooled.Buffer(244);
            byte[] messageBytes = Encoding.UTF8.GetBytes("Hello world");
            this.initialMessage.WriteBytes(messageBytes);
        }

        public override void ChannelActive(IChannelHandlerContext context) => context.WriteAndFlushAsync(this.initialMessage);

        public override void ChannelRead(IChannelHandlerContext context, object message)
        {

            var byteBuffer = message as IByteBuffer;
            if (byteBuffer != null)
            {
                Console.WriteLine("Received from server: " + byteBuffer.ToString(Encoding.UTF8));
                Console.WriteLine("Received from server: " + this.initialMessage);
            }
            context.WriteAsync(message);
        }

        public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Console.WriteLine("Exception: " + exception);
            context.CloseAsync();
        }
    }
}

你可能感兴趣的:(C#)