I am writing a ConnectionHandler
as a part of Kestrel. The idea is that when a client connects, the ConnectionHandler
opens a socket with another server in the network, gets a continuous stream of data and forwards them back to the client. In the meantime, the client can also send data to the ConnectionHandler
that the latter is constantly forwarding to the other server in the network (opened socket).
public override async Task OnConnectedAsync(ConnectionContext connection)
{
TcpClient serverSocket = TcpClient(address, port);
serverSocket.ReceiveTimeout = 10000;
serverSocket.SendTimeout = 10000;
NetworkStream dataStream = serverSocket.GetStream();
dataStream.ReadTimeout = 10000;
dataStream.WriteTimeout = 10000;
Stream clientStreamOut = connection.Transport.Output.AsStream();
Stream clientStreamIn = connection.Transport.Input.AsStream();
Task dataTask = Task.Run(async () =>
{
try
{
await dataStream.CopyToAsync(clientStreamOut);
}
catch
{
await LogsHelper.Log(logStream, LogsHelper.BROKEN_CLIENT_STREAM);
return;
}
}, connection.ConnectionClosed);
Task clientTask = Task.Run(async () =>
{
try
{
await clientStreamIn.CopyToAsync(dataStream);
}
catch
{
await LogsHelper.Log(logStream, LogsHelper.BROKEN_DATA_STREAM);
return;
}
}, connection.ConnectionClosed);
await Task.WhenAny(dataTask, clientTask);
}
I am encountering 3 issues:
- For the socket with the other server, I am using a
TcpClient
and I use aNetworkStream
. Even though I am setting bothReadTimeout
andWriteTimeout
to 10 seconds, for bothTcpClient
andNetworkStream
, the opened socket is waiting forever, even if the other server in the network does not send any data for 5 minutes. - Setting timeout for
clientStreamOut
andclientStreamIn (e.g: clientStreamIn.ReadTimeout = 10000;)
is also failing with an exception that it's not supported for that particular stream. I was wondering, is it possible somehow to provide a timeout? - When a client connects to the
ConnectionHandler
,OnConnectedAsync
is triggered. The issue with the code comes when a client disconnects (either due to network drop or for whatever reason). Sometimes disconnection of the client is being detected and the session terminates, while other times it hangs forever, even if the client has actually been disconnected. I was expecting thatCopyToAsync
will throw an exception in case of a disconnection since I assume thatCopyToAsync
is trying to write, but that's not always the case.
connection.ConnectionClosed
is a CancellationToken
that comes from OnConnectedAsync
, I read here https://github.com/dotnet/runtime/issues/23207 that it can be used in CopyToAsync
. However, I am not sure how I can use it. Also, it is worth to mention that I have zero control over the client code.
I am running the app using Docker
FROM mcr.microsoft.com/dotnet/core/sdk:3.1
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1