// 定义 public abstract class AbstractBootstrap<TBootstrap, TChannel> where TBootstrap : AbstractBootstrap<TBootstrap, TChannel> where TChannel : IChannel // 定义子类 public class Bootstrap : AbstractBootstrap<Bootstrap, IChannel> // 方法实现 public virtual TBootstrap Group(IEventLoopGroup group) { Contract.Requires(group != null);
if (this.group != null) { throw new InvalidOperationException("group has already been set."); } this.group = group; return (TBootstrap)this; } // 使用 var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel<TcpSocketChannel>() .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new EchoClientHandler()); }));
API
客户端引导
1 2 3 4 5 6 7 8 9 10 11 12 13
var group = new MultithreadEventLoopGroup(); var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel<TcpSocketChannel>() .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse("10.10.10.158"), 3000)); Console.ReadLine(); await clientChannel.CloseAsync();
using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using System; using System.Threading.Tasks;
using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Sockets; using System; using System.Net; using System.Threading.Tasks;
namespace EchoClient { class Program { static async Task RunClientAsync() { var group = new MultithreadEventLoopGroup(); try { var bootstrap = new Bootstrap(); bootstrap .Group(group) .Channel<TcpSocketChannel>() .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new EchoClientHandler()); })); IChannel clientChannel = await bootstrap.ConnectAsync(new IPEndPoint(IPAddress.Parse("10.10.10.158"), 3000)); Console.ReadLine(); await clientChannel.CloseAsync(); } catch (Exception ex) { Console.WriteLine(ex); } finally { await group.ShutdownGracefullyAsync(); } } static void Main(string[] args) => RunClientAsync().Wait(); } }
using DotNetty.Buffers; using DotNetty.Transport.Channels.Embedded; using EmbededChannelTest; using System; using System.Collections.Generic; using System.Text; using Xunit;
namespace UnitTest { public class UnitTester { [Fact] public void testFrameDecoder() { IByteBuffer buf = Unpooled.Buffer(); for (int i = 0; i < 9; i++) { buf.WriteByte(i); } IByteBuffer input = buf.Duplicate(); EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3)); // 写数据 // retain能够将buffer的引用计数加1,并且返回这个buffer本身 Assert.True(channel.WriteInbound(input.Retain())); Assert.True(channel.Finish()); // 读数据 IByteBuffer read = channel.ReadInbound<IByteBuffer>(); Assert.Equal(buf.ReadSlice(3), read); read.Release();
// 不需要判断ReadableBytes的ReplayingDecoder public class ToIntDecoder2 : ReplayingDecoder<int> { public ToIntDecoder2(int initialState) : base(initialState) { }
ByteBufferNetty中ByteBuffer的介绍Netty 的数据处理 API 通过两个组件暴露——abstract class ByteBuf 和 interfaceByteBufHolderDotNetty中有AbstractByteBuffer IByteBuffer IByteBufferHolder优点:它可以被用户自定义的缓冲区类型扩展;通过内置的复合缓冲区…
ByteBuffer
Netty中ByteBuffer的介绍
Netty 的数据处理 API 通过两个组件暴露——abstract class ByteBuf 和 interface ByteBufHolder