mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-07 16:06:15 +00:00
Fixed some issues in socket reconnection
This commit is contained in:
parent
5c51822996
commit
e77ca7124e
@ -235,16 +235,25 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Write(LogLevel.Trace, $"Socket {Id} connection succeeded, starting communication");
|
log.Write(LogLevel.Trace, $"Socket {Id} connection succeeded, starting communication");
|
||||||
_sendTask = Task.Factory.StartNew(SendLoopAsync, TaskCreationOptions.LongRunning);
|
_sendTask = Task.Factory.StartNew(SendLoopAsync, default, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap();
|
||||||
_receiveTask = Task.Factory.StartNew(ReceiveLoopAsync, TaskCreationOptions.LongRunning);
|
_receiveTask = Task.Factory.StartNew(ReceiveLoopAsync, default, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap();
|
||||||
if (Timeout != default)
|
if (Timeout != default)
|
||||||
_timeoutTask = Task.Run(CheckTimeoutAsync);
|
_timeoutTask = Task.Run(CheckTimeoutAsync);
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
while (!_startedSent || !_startedReceive)
|
while (!_startedSent || !_startedReceive)
|
||||||
|
{
|
||||||
// Wait for the tasks to have actually started
|
// Wait for the tasks to have actually started
|
||||||
await Task.Delay(10).ConfigureAwait(false);
|
await Task.Delay(10).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if(sw.ElapsedMilliseconds > 5000)
|
||||||
|
{
|
||||||
|
_ = _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", default);
|
||||||
|
log.Write(LogLevel.Debug, $"Socket {Id} startup interupted");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Write(LogLevel.Debug, $"Socket {Id} connected");
|
log.Write(LogLevel.Debug, $"Socket {Id} connected");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -279,8 +288,6 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
if (_closing)
|
if (_closing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_startedSent = false;
|
|
||||||
_startedReceive = false;
|
|
||||||
_closing = true;
|
_closing = true;
|
||||||
var tasksToAwait = new List<Task>();
|
var tasksToAwait = new List<Task>();
|
||||||
if (_socket.State == WebSocketState.Open)
|
if (_socket.State == WebSocketState.Open)
|
||||||
@ -323,6 +330,9 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
log.Write(LogLevel.Debug, $"Socket {Id} resetting");
|
log.Write(LogLevel.Debug, $"Socket {Id} resetting");
|
||||||
_ctsSource = new CancellationTokenSource();
|
_ctsSource = new CancellationTokenSource();
|
||||||
_closing = false;
|
_closing = false;
|
||||||
|
|
||||||
|
while (_sendBuffer.TryDequeue(out _)) { } // Clear send buffer
|
||||||
|
|
||||||
_socket = CreateSocket();
|
_socket = CreateSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,18 +400,11 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
// canceled
|
// canceled
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (IOException ioe)
|
catch (Exception ioe)
|
||||||
{
|
{
|
||||||
// Connection closed unexpectedly, .NET framework
|
// Connection closed unexpectedly, .NET framework
|
||||||
Handle(errorHandlers, ioe);
|
Handle(errorHandlers, ioe);
|
||||||
await CloseInternalAsync(false, true).ConfigureAwait(false);
|
_ = Task.Run(async () => await CloseInternalAsync(false, true).ConfigureAwait(false));
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (WebSocketException wse)
|
|
||||||
{
|
|
||||||
// Connection closed unexpectedly
|
|
||||||
Handle(errorHandlers, wse);
|
|
||||||
await CloseInternalAsync(false, true).ConfigureAwait(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,6 +418,11 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
Handle(errorHandlers, e);
|
Handle(errorHandlers, e);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
log.Write(LogLevel.Trace, $"Socket {Id} Send loop finished");
|
||||||
|
_startedSent = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -424,7 +432,6 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
private async Task ReceiveLoopAsync()
|
private async Task ReceiveLoopAsync()
|
||||||
{
|
{
|
||||||
_startedReceive = true;
|
_startedReceive = true;
|
||||||
|
|
||||||
var buffer = new ArraySegment<byte>(new byte[65536]);
|
var buffer = new ArraySegment<byte>(new byte[65536]);
|
||||||
var received = 0;
|
var received = 0;
|
||||||
try
|
try
|
||||||
@ -451,18 +458,11 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
// canceled
|
// canceled
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (WebSocketException wse)
|
catch (Exception wse)
|
||||||
{
|
{
|
||||||
// Connection closed unexpectedly
|
// Connection closed unexpectedly
|
||||||
Handle(errorHandlers, wse);
|
Handle(errorHandlers, wse);
|
||||||
await CloseInternalAsync(true, false).ConfigureAwait(false);
|
_ = Task.Run(async () => await CloseInternalAsync(true, true).ConfigureAwait(false));
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
// Connection closed unexpectedly, .NET framework
|
|
||||||
Handle(errorHandlers, ioe);
|
|
||||||
await CloseInternalAsync(true, false).ConfigureAwait(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +470,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
{
|
{
|
||||||
// Connection closed unexpectedly
|
// Connection closed unexpectedly
|
||||||
log.Write(LogLevel.Debug, $"Socket {Id} received `Close` message");
|
log.Write(LogLevel.Debug, $"Socket {Id} received `Close` message");
|
||||||
await CloseInternalAsync(true, false).ConfigureAwait(false);
|
_ = Task.Run(async () => await CloseInternalAsync(true, true).ConfigureAwait(false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,21 +517,32 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
|
|
||||||
if (multiPartMessage)
|
if (multiPartMessage)
|
||||||
{
|
{
|
||||||
// Reassemble complete message from memory stream
|
// When the connection gets interupted we might not have received a full message
|
||||||
log.Write(LogLevel.Trace, $"Socket {Id} reassembled message of {memoryStream!.Length} bytes");
|
if (receiveResult?.EndOfMessage == true)
|
||||||
HandleMessage(memoryStream!.ToArray(), 0, (int)memoryStream.Length, receiveResult.MessageType);
|
{
|
||||||
memoryStream.Dispose();
|
// Reassemble complete message from memory stream
|
||||||
|
log.Write(LogLevel.Trace, $"Socket {Id} reassembled message of {memoryStream!.Length} bytes");
|
||||||
|
HandleMessage(memoryStream!.ToArray(), 0, (int)memoryStream.Length, receiveResult.MessageType);
|
||||||
|
memoryStream.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log.Write(LogLevel.Trace, $"Socket {Id} discarding incomplete message of {memoryStream!.Length} bytes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
// Because this is running in a separate task and not awaited until the socket gets closed
|
// Because this is running in a separate task and not awaited until the socket gets closed
|
||||||
// any exception here will crash the receive processing, but do so silently unless the socket get's stopped.
|
// any exception here will crash the receive processing, but do so silently unless the socket gets stopped.
|
||||||
// Make sure we at least let the owner know there was an error
|
// Make sure we at least let the owner know there was an error
|
||||||
Handle(errorHandlers, e);
|
Handle(errorHandlers, e);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
log.Write(LogLevel.Trace, $"Socket {Id} Receive loop finished");
|
||||||
|
_startedReceive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user