主要是作java开发的,这一段时间用到了netty,权衡之下编解码框架选择了messagepack,当然protobuf同样是是很好的一种编解码框架,只是项目中需要传对象需要支持byte[]形式,而protobuf并不支持,经过努力也只能封装出支持list的数据结构,能力有限,就选择了messagepack。
对于java方面的用法就不多说了,资料有很多,尤其推荐《netty权威指南》。
废话不多说了,直接说C#的开发了,在网上似乎没有完整的整合资料,就贴出来,和大家分享以下。不过本人并非专业的C#开发,又不完善或不恰当之处,望理解并告知。
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
依赖添加完毕
messagepack的安装
对于c#开发来说,想要运用messagepack在网上的援助同样很少,大概最先搜索到的都是这一篇:
https://www.cnblogs.com/Leo_wl/p/8143259.html
不过这一篇博客,写的很详细,包括对messagepack与其他编解码框架的性能对比分析、依赖导入方法,以及基础的应用,希望各位去看一下,这里就不做再做摘录了。
整合dotnettymsgpack编解码框架
完成前两个步骤就可以进行dotnetty+msgpack开发了,就不多说了,直接贴代码:
class MsgPackEcode : MessageToByteEncoder
服务端
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();
}
}
}