public void Start() { try { _bootstrap.Group(_bossGroup, _workerGroup); _bootstrap.Channel <TcpServerSocketChannel>(); _bootstrap.Option(ChannelOption.SoBacklog, 100); _bootstrap.ChildOption(ChannelOption.SoKeepalive, true); _bootstrap.Option(ChannelOption.TcpNodelay, true); _bootstrap.Option(ChannelOption.SoReuseport, true); _bootstrap.ChildOption(ChannelOption.SoReuseport, true); _bootstrap.Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default); _bootstrap.ChildOption(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default); _bootstrap.ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast("DotNetty-enc", new LengthFieldPrepender(4)); pipeline.AddLast("DotNetty-dec", new LengthFieldBasedFrameDecoder(GlobalConfig.Config.MaxFrameLength, 0, 4, 0, 4)); pipeline.AddLast(new MasterMessageHandler((IChannelMessageHandler)this)); })); _bootstrapChannel = _bootstrap.BindAsync(_localPort).Result; Logger.Log.Info(false, "主节点侦听端口:" + GlobalConfig.Config.MasterListenPort); } catch (Exception ex) { Logger.Log.Error(true, "", ex); } }
private void Initialize() { if (Initializer == null) { Out.QuickLog("Abstract server failed to start on Port " + Port + " due to the server's initializer being NULL"); return; } _bootstrap.Group(_bossEventLoopGroup, _workerEventLoopGroup); // Set Channel Type to Tcp. _bootstrap.Channel <TcpServerSocketChannel>(); // Set Server Options _bootstrap.Option(ChannelOption.SoLinger, 0); _bootstrap.Option(ChannelOption.SoBacklog, Backlog); _bootstrap.ChildHandler(Initializer); _bootstrap.ChildOption(ChannelOption.SoLinger, 0); _bootstrap.ChildOption(ChannelOption.SoKeepalive, true); _bootstrap.ChildOption(ChannelOption.TcpNodelay, true); _bootstrap.ChildOption(ChannelOption.SoReuseaddr, true); }
protected void Init() { _bootstrap.Group(_bossEventLoopGroup, _workerEventLoopGroup); _bootstrap.Channel <TcpServerSocketChannel>(); _bootstrap.Option(ChannelOption.SoLinger, 0); _bootstrap.Option(ChannelOption.SoBacklog, Backlog); _bootstrap.Handler(new LoggingHandler(LogLevel.INFO)); _bootstrap.ChildHandler(new InboundSessionInitializer(inboundSession)); _bootstrap.ChildOption(ChannelOption.SoLinger, 0); _bootstrap.ChildOption(ChannelOption.SoKeepalive, true); _bootstrap.ChildOption(ChannelOption.TcpNodelay, true); _bootstrap.ChildOption(ChannelOption.SoReuseaddr, true); }
/// <summary> /// init netty write buffer water mark /// </summary> private void initWriteBufferWaterMark() { int lowWaterMark = netty_buffer_low_watermark(); int highWaterMark = netty_buffer_high_watermark(); if (lowWaterMark > highWaterMark) { throw new System.ArgumentException(string.Format("[server side] bolt netty high water mark {{{0}}} should not be smaller than low water mark {{{1}}} bytes)", highWaterMark, lowWaterMark)); } else { logger.LogWarning("[server side] bolt netty low water mark is {} bytes, high water mark is {} bytes", lowWaterMark, highWaterMark); } bootstrap.ChildOption(ChannelOption.WriteBufferLowWaterMark, lowWaterMark); bootstrap.ChildOption(ChannelOption.WriteBufferHighWaterMark, highWaterMark); }
protected override void Configure(ServerBootstrap sb, Bootstrap cb, IByteBufferAllocator allocator) { sb.LocalAddress(NewSocketAddress()); sb.Option(ChannelOption.Allocator, allocator); sb.ChildOption(ChannelOption.Allocator, allocator); cb.Option(ChannelOption.Allocator, allocator); }
private async Task TestConditionalWritability0(ServerBootstrap sb, Bootstrap cb) { IChannel serverChannel = null; IChannel clientChannel = null; try { int expectedBytes = 100 * 1024 * 1024; int maxWriteChunkSize = 16 * 1024; CountdownEvent latch = new CountdownEvent(1); sb.ChildOption(ChannelOption.WriteBufferLowWaterMark, 8 * 1024); sb.ChildOption(ChannelOption.WriteBufferHighWaterMark, 16 * 1024); sb.ChildHandler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelDuplexHandler0(expectedBytes, maxWriteChunkSize)); })); serverChannel = await sb.BindAsync(); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelInboundHandlerAdapter0(expectedBytes, latch)); })); clientChannel = await cb.ConnectAsync(serverChannel.LocalAddress); latch.Wait(); } finally { if (clientChannel != null) { await clientChannel.CloseAsync(); } if (serverChannel != null) { await serverChannel.CloseAsync(); } Task.WaitAll( sb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), sb.ChildGroup().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), cb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5))); } }
protected void Initialize() { _bootstrap.Group(_bossEventLoopGroup, _workerEventLoopGroup); // Set Channel Type to Tcp. _bootstrap.Channel <TcpServerSocketChannel>(); // Set Server Options _bootstrap.Option(ChannelOption.SoLinger, 0); _bootstrap.Option(ChannelOption.SoBacklog, Backlog); _bootstrap.ChildHandler(new GameSessionInitializer()); _bootstrap.ChildOption(ChannelOption.SoLinger, 0); _bootstrap.ChildOption(ChannelOption.SoKeepalive, true); _bootstrap.ChildOption(ChannelOption.TcpNodelay, true); _bootstrap.ChildOption(ChannelOption.SoReuseaddr, true); }
public void TestReuseFd(ServerBootstrap sb, Bootstrap cb) { sb.ChildOption(ChannelOption.AutoRead, true); cb.Option(ChannelOption.AutoRead, true); // Use a number which will typically not exceed /proc/sys/net/core/somaxconn (which is 128 on linux by default // often). int numChannels = 100; AtomicReference <Exception> globalException = new AtomicReference <Exception>(); AtomicInteger serverRemaining = new AtomicInteger(numChannels); AtomicInteger clientRemaining = new AtomicInteger(numChannels); IPromise serverDonePromise = new DefaultPromise(); IPromise clientDonePromise = new DefaultPromise(); sb.ChildHandler(new ActionChannelInitializer <IChannel>(sch => { ReuseFdHandler sh = new ReuseFdHandler( false, globalException, serverRemaining, serverDonePromise); sch.Pipeline.AddLast("handler", sh); })); cb.Handler(new ActionChannelInitializer <IChannel>(sch => { ReuseFdHandler ch = new ReuseFdHandler( true, globalException, clientRemaining, clientDonePromise); sch.Pipeline.AddLast("handler", ch); })); IChannel sc = sb.BindAsync().GetAwaiter().GetResult(); for (int i = 0; i < numChannels; i++) { cb.ConnectAsync(sc.LocalAddress).ContinueWith(t => { if (!t.IsSuccess()) { clientDonePromise.TrySetException(t.Exception); } }); } clientDonePromise.Task.GetAwaiter().GetResult(); serverDonePromise.Task.GetAwaiter().GetResult(); sc.CloseAsync().GetAwaiter().GetResult(); if (globalException.Value is object) { throw globalException.Value; } }
private static void TestAutoCloseFalseDoesShutdownOutput0(bool allowHalfClosed, bool clientIsLeader, ServerBootstrap sb, Bootstrap cb) { const int expectedBytes = 100; CountdownEvent serverReadExpectedLatch = new CountdownEvent(1); CountdownEvent doneLatch = new CountdownEvent(1); AtomicReference <Exception> causeRef = new AtomicReference <Exception>(); IChannel serverChannel = null; IChannel clientChannel = null; try { cb.Option(ChannelOption.AllowHalfClosure, allowHalfClosed) .Option(ChannelOption.AutoClose, false) .Option(ChannelOption.SoLinger, 0); sb.ChildOption(ChannelOption.AllowHalfClosure, allowHalfClosed) .ChildOption(ChannelOption.AutoClose, false) .ChildOption(ChannelOption.SoLinger, 0); SimpleChannelInboundHandler <IByteBuffer> leaderHandler = new AutoCloseFalseLeader(expectedBytes, serverReadExpectedLatch, doneLatch, causeRef); SimpleChannelInboundHandler <IByteBuffer> followerHandler = new AutoCloseFalseFollower(expectedBytes, serverReadExpectedLatch, doneLatch, causeRef); sb.ChildHandler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(clientIsLeader ? followerHandler : leaderHandler); })); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(clientIsLeader ? leaderHandler : followerHandler); })); serverChannel = sb.BindAsync().GetAwaiter().GetResult(); clientChannel = cb.ConnectAsync(serverChannel.LocalAddress).GetAwaiter().GetResult(); doneLatch.Wait(); Assert.Null(causeRef.Value); } finally { if (clientChannel != null) { clientChannel.CloseAsync().GetAwaiter().GetResult(); } if (serverChannel != null) { serverChannel.CloseAsync().GetAwaiter().GetResult(); } } }
void Bootstrap() { bootstrap.Group(parentEventLoopGroup, eventLoopGroup); bootstrap.Option(ChannelOption.SoBacklog, ListenBacklogSize); bootstrap.ChildOption(ChannelOption.Allocator, PooledByteBufferAllocator.Default); bootstrap.Channel <TcpServerSocketChannel>(); bootstrap.Option(ChannelOption.ConnectTimeout, DefaultConnectionIdleTimeout); bootstrap.ChildHandler(new ActionChannelInitializer <ISocketChannel>(channel => { IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new LengthFieldBasedFrameDecoder(ByteOrder.BigEndian, 4096, 1, 4, -5, 0, true)); pipeline.AddLast(new BmpDecoder(), new BmpMessageHandler()); })); }
void SimpleEcho0(ServerBootstrap sb, Bootstrap cb, bool additionalExecutor, bool autoRead) { var sh = new EchoHandler(autoRead, this.data, this.output); var ch = new EchoHandler(autoRead, this.data, this.output); if (additionalExecutor) { sb.ChildHandler(new ActionChannelInitializer <TcpChannel>(channel => { channel.Pipeline.AddLast(this.group, sh); })); cb.Handler(new ActionChannelInitializer <TcpChannel>(channel => { channel.Pipeline.AddLast(this.group, ch); })); } else { sb.ChildHandler(sh); sb.Handler(new ErrorOutputHandler(this.output)); cb.Handler(ch); } sb.ChildOption(ChannelOption.AutoRead, autoRead); cb.Option(ChannelOption.AutoRead, autoRead); // start server Task <IChannel> task = sb.BindAsync(LoopbackAnyPort); Assert.True(task.Wait(DefaultTimeout), "Server bind timed out"); this.serverChannel = task.Result; Assert.NotNull(this.serverChannel.LocalAddress); var endPoint = (IPEndPoint)this.serverChannel.LocalAddress; // connect to server task = cb.ConnectAsync(endPoint); Assert.True(task.Wait(DefaultTimeout), "Connect to server timed out"); this.clientChannel = task.Result; Assert.NotNull(this.clientChannel.LocalAddress); for (int i = 0; i < this.data.Length;) { int length = Math.Min(this.random.Next(1024 * 64), this.data.Length - i); IByteBuffer buf = Unpooled.WrappedBuffer(this.data, i, length); this.clientChannel.WriteAndFlushAsync(buf); i += length; } Assert.True(Task.WhenAll(ch.Completion, sh.Completion).Wait(DefaultTimeout), "Echo read/write timed out"); }
private async Task TestAutoReadOnDataReadImmediately0(ServerBootstrap sb, Bootstrap cb) { IChannel serverChannel = null; IChannel clientChannel = null; try { sb.Option(ChannelOption.AutoRead, true); sb.ChildOption(ChannelOption.AutoRead, true); cb.Option(ChannelOption.AutoRead, true); CountdownEvent serverReadLatch = new CountdownEvent(1); CountdownEvent clientReadLatch = new CountdownEvent(1); sb.ChildHandler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new SimpleChannelInboundHandler0(serverReadLatch)); })); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new SimpleChannelInboundHandler1(clientReadLatch)); })); serverChannel = await sb.BindAsync(); clientChannel = await cb.ConnectAsync(serverChannel.LocalAddress); clientChannel.WriteAndFlushAsync(clientChannel.Allocator.Buffer().WriteZero(1)).Ignore(); serverReadLatch.Wait(); clientReadLatch.Wait(); } finally { if (serverChannel != null) { await serverChannel.CloseAsync(); } if (clientChannel != null) { await clientChannel.CloseAsync(); } Task.WaitAll( sb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), sb.ChildGroup().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), cb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5))); } }
/// <summary> /// Starts the network. /// </summary> public static void StartNetwork() { var boss = new MultithreadEventLoopGroup(1); var worker = new MultithreadEventLoopGroup(); var bootstrap = new ServerBootstrap(); bootstrap.Group(boss, worker); bootstrap.Channel <TcpServerSocketChannel>(); bootstrap.ChildHandler(new ActionChannelInitializer <ISocketChannel>((ch) => { IChannelPipeline pipeline = ch.Pipeline; pipeline.AddLast("encoder", new HandshakeEncoder()); pipeline.AddLast("decoder", new HandshakeDecoder()); pipeline.AddLast("handler", new NetworkHandler(ch)); })); bootstrap.ChildOption(ChannelOption.TcpNodelay, true); bootstrap.BindAsync(IPAddress.Parse(Constants.SERVER_IP), Constants.SERVER_PORT); }
private async Task TestSoLingerZeroCausesOnlyRstOnClose0(ServerBootstrap sb, Bootstrap cb) { AtomicReference <IChannel> serverChannelRef = new AtomicReference <IChannel>(); AtomicReference <Exception> throwableRef = new AtomicReference <Exception>(); CountdownEvent latch = new CountdownEvent(1); CountdownEvent latch2 = new CountdownEvent(1); // SO_LINGER=0 means that we must send ONLY a RST when closing (not a FIN + RST). sb.ChildOption(ChannelOption.SoLinger, 0); sb.ChildHandler(new ActionChannelInitializer <IChannel>(ch => { serverChannelRef.CompareAndSet(null, ch); latch.SafeSignal(); })); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelInboundHandlerAdapter0(throwableRef, latch2)); })); IChannel sc = await sb.BindAsync(); IChannel cc = await cb.ConnectAsync(sc.LocalAddress); // Wait for the server to get setup. latch.Wait(); // The server has SO_LINGER=0 and so it must send a RST when close is called. serverChannelRef.Value.CloseAsync().Ignore(); // Wait for the client to get channelInactive. latch2.Wait(); // Verify the client received a RST. var cause = throwableRef.Value; if (cause is object) { Assert.True(cause is SocketException, "actual [type, message]: [" + cause.GetType() + ", " + cause.Message + "]"); //AssertRstOnCloseException((SocketException)cause, cc); Assert.True(cause.Message.Contains("reset") || cause.Message.Contains("closed"), "actual message: " + cause.Message); } }
protected void Init() { InternalLoggerFactory.DefaultFactory.AddProvider( new ConsoleLoggerProvider( (text, level) => level >= Microsoft.Extensions.Logging.LogLevel.Warning, true) ); _bootstrap.Group(_bossEventLoopGroup, _workerEventLoopGroup); // 设置主和工作线程组 _bootstrap.Channel <TcpServerSocketChannel>(); // 设置通道模式为TcpSocket //当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度 _bootstrap.Option(ChannelOption.SoBacklog, Backlog);//ChannelOption.SO_BACKLOG, 1024 _bootstrap.Handler(new LoggingHandler(LogLevel.WARN)); //_bootstrap.ChildHandler(new InboundSessionInitializer(inboundSession)); //_bootstrap.ChildOption(ChannelOption.SoLinger,0);//Socket关闭时的延迟时间(秒) //注册 _bootstrap.ChildHandler(new DataServerInitializer()); _bootstrap.ChildOption(ChannelOption.SoKeepalive, true);//是否启用心跳保活机制 //_bootstrap.ChildOption(ChannelOption.TcpNodelay,true);//启用/禁用Nagle算法 }
private static async Task TestStringEcho0(ServerBootstrap sb, Bootstrap cb, bool autoRead, ITestOutputHelper output) { sb.ChildOption(ChannelOption.AutoRead, autoRead); cb.Option(ChannelOption.AutoRead, autoRead); IPromise serverDonePromise = new DefaultPromise(); IPromise clientDonePromise = new DefaultPromise(); StringEchoHandler sh = new StringEchoHandler(autoRead, serverDonePromise, output); StringEchoHandler ch = new StringEchoHandler(autoRead, clientDonePromise, output); sb.ChildHandler(new ActionChannelInitializer <IChannel>(sch => { sch.Pipeline.AddLast("framer", new DelimiterBasedFrameDecoder(512, Delimiters.LineDelimiter())); sch.Pipeline.AddLast("decoder", new StringDecoder(Encoding.ASCII)); sch.Pipeline.AddBefore("decoder", "encoder", new StringEncoder(Encoding.ASCII)); sch.Pipeline.AddAfter("decoder", "handler", sh); })); cb.Handler(new ActionChannelInitializer <IChannel>(sch => { sch.Pipeline.AddLast("framer", new DelimiterBasedFrameDecoder(512, Delimiters.LineDelimiter())); sch.Pipeline.AddLast("decoder", new StringDecoder(Encoding.ASCII)); sch.Pipeline.AddBefore("decoder", "encoder", new StringEncoder(Encoding.ASCII)); sch.Pipeline.AddAfter("decoder", "handler", ch); })); IChannel sc = await sb.BindAsync(); IChannel cc = await cb.ConnectAsync(sc.LocalAddress); for (int i = 0; i < s_data.Length; i++) { string element = s_data[i]; string delimiter = s_random.Next(0, 1) == 1 ? "\r\n" : "\n"; await cc.WriteAndFlushAsync(element + delimiter); } await ch._donePromise.Task; await sh._donePromise.Task; await sh._channel.CloseAsync(); await ch._channel.CloseAsync(); await sc.CloseAsync(); if (sh._exception.Value != null && !(sh._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc && chexc.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw sh._exception.Value; } if (ch._exception.Value != null && !(ch._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc1 && chexc1.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw ch._exception.Value; } if (sh._exception.Value != null) { throw sh._exception.Value; } if (ch._exception.Value != null) { throw ch._exception.Value; } }
private async Task TestGatheringWrite0( ServerBootstrap sb, Bootstrap cb, byte[] data, bool composite, bool autoRead) { sb.ChildOption(ChannelOption.AutoRead, autoRead); cb.Option(ChannelOption.AutoRead, autoRead); IPromise serverDonePromise = new DefaultPromise(); TestServerHandler sh = new TestServerHandler(autoRead, serverDonePromise, data.Length); TestHandler ch = new TestHandler(autoRead); cb.Handler(ch); sb.ChildHandler(sh); IChannel sc = await sb.BindAsync(); IChannel cc = await cb.ConnectAsync(sc.LocalAddress); for (int i = 0; i < data.Length;) { int length = Math.Min(s_random.Next(1024 * 8), data.Length - i); if (composite && i % 2 == 0) { int firstBufLength = length / 2; CompositeByteBuffer comp = Unpooled.CompositeBuffer(); comp.AddComponent(true, Unpooled.WrappedBuffer(data, i, firstBufLength)) .AddComponent(true, Unpooled.WrappedBuffer(data, i + firstBufLength, length - firstBufLength)); cc.WriteAsync(comp).Ignore(); } else { cc.WriteAsync(Unpooled.WrappedBuffer(data, i, length)).Ignore(); } i += length; } var cf = cc.WriteAndFlushAsync(Unpooled.Empty); Assert.NotEqual(cc.VoidPromise().Task, cf); try { Assert.True(cf.Wait(60000)); await cf; } catch (Exception) { throw; } await serverDonePromise.Task; await sh._channel.CloseAsync(); await ch._channel.CloseAsync(); await sc.CloseAsync(); if (sh._exception.Value != null && !(sh._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc && chexc.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw sh._exception.Value; } if (sh._exception.Value != null) { throw sh._exception.Value; } if (ch._exception.Value != null && !(ch._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc1 && chexc1.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw ch._exception.Value; } if (ch._exception.Value != null) { throw ch._exception.Value; } IByteBuffer expected = Unpooled.WrappedBuffer(data); Assert.Equal(expected, sh._received); expected.Release(); sh._received.Release(); }
private static async Task TestFixedLengthEcho0(ServerBootstrap sb, Bootstrap cb, bool autoRead) { EchoHandler sh = new EchoHandler(autoRead); EchoHandler ch = new EchoHandler(autoRead); sb.ChildOption(ChannelOption.AutoRead, autoRead); sb.ChildHandler(new ActionChannelInitializer <IChannel>(sch => { sch.Pipeline.AddLast("decoder", new FixedLengthFrameDecoder(1024)); sch.Pipeline.AddAfter("decoder", "handler", sh); })); cb.Option(ChannelOption.AutoRead, autoRead); cb.Handler(new ActionChannelInitializer <IChannel>(sch => { sch.Pipeline.AddLast("decoder", new FixedLengthFrameDecoder(1024)); sch.Pipeline.AddAfter("decoder", "handler", ch); })); IChannel sc = await sb.BindAsync(); IChannel cc = await cb.ConnectAsync(sc.LocalAddress); for (int i = 0; i < s_data.Length;) { int length = Math.Min(s_random.Next(1024 * 3), s_data.Length - i); cc.WriteAndFlushAsync(Unpooled.WrappedBuffer(s_data, i, length)).Ignore(); i += length; } while (ch._counter < s_data.Length) { if (sh._exception.Value != null) { break; } if (ch._exception.Value != null) { break; } Thread.Sleep(50); } while (sh._counter < s_data.Length) { if (sh._exception.Value != null) { break; } if (ch._exception.Value != null) { break; } Thread.Sleep(50); } await sh._channel.CloseAsync(); await ch._channel.CloseAsync(); await sc.CloseAsync(); if (sh._exception.Value != null && !(sh._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc && chexc.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw sh._exception.Value; } if (ch._exception.Value != null && !(ch._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc1 && chexc1.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw ch._exception.Value; } if (sh._exception.Value != null) { throw sh._exception.Value; } if (ch._exception.Value != null) { throw ch._exception.Value; } }
private async Task TestSimpleEcho0( ServerBootstrap sb, Bootstrap cb, bool additionalExecutor, bool voidPromise, bool autoRead) { EchoHandler sh = new EchoHandler(autoRead); EchoHandler ch = new EchoHandler(autoRead); if (additionalExecutor) { sb.ChildHandler(new ActionChannelInitializer <IChannel>(c => { c.Pipeline.AddLast(_group, sh); })); cb.Handler(new ActionChannelInitializer <IChannel>(c => { c.Pipeline.AddLast(_group, ch); })); } else { sb.ChildHandler(sh); sb.Handler(new ChannelHandlerAdapter()); cb.Handler(ch); } sb.ChildOption(ChannelOption.AutoRead, autoRead); cb.Option(ChannelOption.AutoRead, autoRead); IChannel sc = await sb.BindAsync(); IChannel cc = await cb.ConnectAsync(sc.LocalAddress); for (int i = 0; i < s_data.Length;) { int length = Math.Min(s_random.Next(1024 * 64), s_data.Length - i); IByteBuffer buf = Unpooled.WrappedBuffer(s_data, i, length); if (voidPromise) { Assert.Equal(cc.VoidPromise().Task, cc.WriteAndFlushAsync(buf, cc.VoidPromise())); } else { Assert.NotEqual(cc.VoidPromise().Task, cc.WriteAndFlushAsync(buf)); } i += length; } while (ch._counter < s_data.Length) { if (sh._exception.Value != null) { break; } if (ch._exception.Value != null) { break; } Thread.Sleep(50); } while (sh._counter < s_data.Length) { if (sh._exception.Value != null) { break; } if (ch._exception.Value != null) { break; } Thread.Sleep(50); } await sh._channel.CloseAsync(); await ch._channel.CloseAsync(); await sc.CloseAsync(); if (sh._exception.Value != null && !(sh._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc && chexc.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw sh._exception.Value; } if (ch._exception.Value != null && !(ch._exception.Value is SocketException || (sh._exception.Value is ChannelException chexc1 && chexc1.InnerException is OperationException) || sh._exception.Value is OperationException)) { throw ch._exception.Value; } if (sh._exception.Value != null) { throw sh._exception.Value; } if (ch._exception.Value != null) { throw ch._exception.Value; } }
private async Task TestAutoReadOffNoDataReadUntilReadCalled0(ServerBootstrap sb, Bootstrap cb, bool isLibuvServer) { IChannel serverChannel = null; IChannel clientChannel = null; const int sleepMs = 100; try { sb.Option(ChannelOption.AutoRead, isLibuvServer); // LibuvServer 不支持 No-AutoRead sb.ChildOption(ChannelOption.AutoRead, false); cb.Option(ChannelOption.AutoRead, false); CountdownEvent serverReadyLatch = new CountdownEvent(1); CountdownEvent acceptorReadLatch = new CountdownEvent(1); CountdownEvent serverReadLatch = new CountdownEvent(1); CountdownEvent clientReadLatch = new CountdownEvent(1); AtomicReference <IChannel> serverConnectedChannelRef = new AtomicReference <IChannel>(); sb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelInboundHandlerAdapter0(acceptorReadLatch)); })); sb.ChildHandler(new ActionChannelInitializer <IChannel>(ch => { serverConnectedChannelRef.Value = ch; ch.Pipeline.AddLast(new SimpleChannelInboundHandler0(serverReadLatch)); serverReadyLatch.SafeSignal(); })); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new SimpleChannelInboundHandler1(clientReadLatch)); })); serverChannel = await sb.BindAsync(); clientChannel = await cb.ConnectAsync(serverChannel.LocalAddress); await clientChannel.WriteAndFlushAsync(clientChannel.Allocator.Buffer().WriteZero(1)); // The acceptor shouldn't read any data until we call read() below, but give it some time to see if it will. if (!isLibuvServer) { Thread.Sleep(sleepMs); Assert.Equal(1, acceptorReadLatch.CurrentCount); serverChannel.Read(); serverReadyLatch.Wait(); } IChannel serverConnectedChannel = serverConnectedChannelRef.Value; Assert.NotNull(serverConnectedChannel); // Allow some amount of time for the server peer to receive the message (which isn't expected to happen // until we call read() below). Thread.Sleep(sleepMs); Assert.Equal(1, serverReadLatch.CurrentCount); serverConnectedChannel.Read(); serverReadLatch.Wait(); // Allow some amount of time for the client to read the echo. Thread.Sleep(sleepMs); Assert.Equal(1, clientReadLatch.CurrentCount); clientChannel.Read(); clientReadLatch.Wait(); } finally { if (serverChannel != null) { await serverChannel.CloseAsync(); } if (clientChannel != null) { await clientChannel.CloseAsync(); } Task.WaitAll( sb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), sb.ChildGroup().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), cb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5))); } }
private async Task TestCompositeBufferPartialWriteDoesNotCorruptData0(ServerBootstrap sb, Bootstrap cb) { // The scenario is the following: // Limit SO_SNDBUF so that a single buffer can be written, and part of a CompositeByteBuf at the same time. // We then write the single buffer, the CompositeByteBuf, and another single buffer and verify the data is not // corrupted when we read it on the other side. IChannel serverChannel = null; IChannel clientChannel = null; try { Random r = new Random(); int soSndBuf = 1024; IByteBufferAllocator alloc = ByteBufferUtil.DefaultAllocator; IByteBuffer expectedContent = alloc.Buffer(soSndBuf * 2); expectedContent.WriteBytes(NewRandomBytes(expectedContent.WritableBytes, r)); CountdownEvent latch = new CountdownEvent(1); AtomicReference <object> clientReceived = new AtomicReference <object>(); sb.ChildOption(ChannelOption.SoSndbuf, soSndBuf) .ChildHandler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelInboundHandlerAdapter0(expectedContent, latch, clientReceived, soSndBuf)); })); cb.Handler(new ActionChannelInitializer <IChannel>(ch => { ch.Pipeline.AddLast(new ChannelInboundHandlerAdapter1(expectedContent, latch, clientReceived)); })); serverChannel = await sb.BindAsync(); clientChannel = await cb.ConnectAsync(serverChannel.LocalAddress); latch.Wait(); object received = clientReceived.Value; if (received is IByteBuffer) { IByteBuffer actual = (IByteBuffer)received; Assert.Equal(expectedContent, actual); expectedContent.Release(); actual.Release(); } else { expectedContent.Release(); throw (Exception)received; } } finally { if (clientChannel != null) { await clientChannel.CloseAsync(); } if (serverChannel != null) { await serverChannel.CloseAsync(); } Task.WaitAll( sb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), sb.ChildGroup().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5)), cb.Group().ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(5))); } }