Azure / Azure/DotNetty

Connection does not disconnect after WriteAndFlushAsync

Open
#479 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
4.3k
Forks
1k
PR merge metrics
No merged PRs in 30d

Description

Hi,

My understanding was that, as soon as a client connects to the server and response is sent to the client, that connection is considered complete and the client will be disconnected and channel inactive. I see that the connection persists and the method ChannelInactive is never instantiated and when new clients connect, it uses the same channel to send the connection. Please let me know why this is happening so, or if my understanding is incorrect. ie., On WriteAndFlushAsync(), I thought the connection would disconnect. Is this not the case? Do I have to explicitly mention a Channel.DisconnectAsync()? (My service acts as a server and incoming connections keep coming)

Given below is my code:

`public class PipelinesHandler: ChannelHandlerAdapter
{
private readonly ILoggerService _loggerService;
private readonly IMessageProcessor _messageProcessor;
private readonly ISocketPipe _socketPipe;
private IByteBuffer _byteBuffer;
private readonly ITracerService _tracerService;
private readonly TraceHelper _traceHelper;
private Pipe _pipe;

public PipelinesHandler(ILoggerService loggerService, IMessageProcessor messageProcessor, ISocketPipe pipe, ITracerService tracerService)
{
_loggerService = loggerService;
if(_loggerService == null)
{
throw new ArgumentNullException($"ILoggerService object is required.");
}
_messageProcessor = messageProcessor;
if (_messageProcessor == null)
{
throw new ArgumentNullException($"IMessageProcessor object is required.");
}
_socketPipe = pipe;
if (_socketPipe == null)
{
throw new ArgumentNullException($"ISocketPipe object cannot be null.");
}
_tracerService = tracerService;
if (_tracerService == null)
{
throw new ArgumentNullException($"ISocketPipe object cannot be null.");
}
_traceHelper = new TraceHelper(_tracerService);
}

public override void ChannelActive(IChannelHandlerContext context)
{
_loggerService.Info(new LogMessage
{
ClassName = "PipelinesHandler",
MethodName = "ChannelActive",
MessageText = $"Channel {context.Channel.Id} is Active. Current Thread: {Thread.CurrentThread.ManagedThreadId}"
});
_pipe = new Pipe();
// base.ChannelActive(context);
}

public override async void ChannelRead(IChannelHandlerContext ctx, object msg)
{

try
{
var buffer = msg as IByteBuffer;

if (buffer != null)
{
if (buffer.IsReadable())
{
var bytesReceived = new byte[buffer.ReadableBytes];
buffer.GetBytes(0, bytesReceived);
_loggerService.Info(new LogMessage
{
ClassName = "PipelinesHandler",
MethodName = "ChannelRead",
MessageText = $"Message as is read from the channel {ctx.Channel.Id}: {buffer.ToString(Encoding.ASCII)}"
});
var dataFromPipe = await ProcessData(bytesReceived);
if (!string.IsNullOrEmpty(dataFromPipe))
{

var result = await _messageProcessor.ProcessMessage(dataFromPipe);
if (!string.IsNullOrEmpty(result))
{
_loggerService.Info(new LogMessage { MessageText = $"Sending result to client...Result: {result}. " });
byte[] messageBytes = Encoding.ASCII.GetBytes(result);
_byteBuffer = Unpooled.Buffer(messageBytes.Length);
var finalData = _byteBuffer.WriteBytes(messageBytes);
await ctx.WriteAndFlushAsync(finalData);
}
}
}
}
}
}
catch (Exception e)
{
_loggerService.Error(e, new LogMessage
{
ClassName = "PipelinesHandler",
MethodName = "ChannelRead",
MessageText = $"Error occurred in Connection. Error: {e.Message}"
});
}
}

public override void ChannelReadComplete(IChannelHandlerContext context)
{
//context.Flush();
//base.ChannelReadComplete(context);
}

public override void ChannelInactive(IChannelHandlerContext context)
{
_loggerService.Info(new LogMessage
{
ClassName = "PipelinesHandler",
MethodName = "ChannelInactive",
MessageText = $"Channel {context.Channel.Id} is inactive. Current Thread: {Thread.CurrentThread.ManagedThreadId}"
});
_pipe.Writer.Complete();
//base.ChannelInactive(context);
}

public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
{
_loggerService.Error(exception, new LogMessage
{
ClassName = "PipelinesHandler",
MethodName = "ExceptionCaught",
MessageText = $"Exception occurred in ChannelRead method of DotNetty. Exception: {exception.Message}"
});
context.CloseAsync();
}

private async Task ProcessData(object msg)
{
try
{
// process incoming data and return response
}
catch(Exception ex)
{
_loggerService.Error(ex, new LogMessage { MessageText = "Error occured in ProcessData" });
return "";
}
}

#region IDisposable Members

///
/// Close and dispose.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

///
/// Close and dispose.
///
///
protected virtual void Dispose(bool disposing)
{
if (disposing)
{

}
}

///
/// Finalizer
///
~PipelinesHandler()
{
Dispose(false);
}

#endregion
}`

Thanks,

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.