doghappy / socket.io-client-csharp

socket.io-client implemention for .NET
MIT License
729 stars 125 forks source link

Exception when sending many small packets #250

Open Jakobi-mirsk opened 2 years ago

Jakobi-mirsk commented 2 years ago

hi I have a test setup where i make 100 connections that send a small message 3 times pr. second. I keep getting this error and I don't know why. Maybe some one can help shed some light on it.

System.AggregateException: One or more errors occurred. ---> System.Net.WebSockets.WebSocketException: An internal WebSocket error occurred. Please see the innerException, if present, for more details. ---> System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) at System.Net.Sockets.NetworkStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.Net.Security._SslStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback asyncCallback, Object asyncState) at System.Net.TlsStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback asyncCallback, Object asyncState) at System.Net.PooledStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.IO.Stream.<>c.b53_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state) at System.Threading.Tasks.TaskFactory1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func5 beginMethod, Func`3 endMethod) at System.IO.Stream.BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count) at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.DelegatedStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.WebSocketConnection.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.DelegatedStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.<>n1(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.WebSockets.WebSocketBase.d48.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at System.Net.WebSockets.WebSocketBase.WebSocketOperation.d19.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.WebSockets.WebSocketBase.d47.MoveNext() --- End of inner exception stack trace --- at System.Net.WebSockets.WebSocketBase.ThrowIfConvertibleException(String methodName, Exception exception, CancellationToken cancellationToken, Boolean aborted) at System.Net.WebSockets.WebSocketBase.d47.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.DefaultClientWebSocket.d12.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.WebSocketTransport.d36.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.WebSocketTransport.d37.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Routers.WebSocketRouter.d7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Routers.Router.d49.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.SocketIO.d102.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.SocketIO.d__101.MoveNext() --- End of inner exception stack trace --- ---> (Inner Exception #0) System.Net.WebSockets.WebSocketException (0x80004005): An internal WebSocket error occurred. Please see the innerException, if present, for more details. ---> System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine at System.Net.Sockets.Socket.BeginSend(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state) at System.Net.Sockets.NetworkStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) --- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.Net.Security._SslStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback asyncCallback, Object asyncState) at System.Net.TlsStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback asyncCallback, Object asyncState) at System.Net.PooledStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state) at System.IO.Stream.<>c.b53_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state) at System.Threading.Tasks.TaskFactory1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func5 beginMethod, Func`3 endMethod) at System.IO.Stream.BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count) at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.DelegatedStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.WebSocketConnection.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.DelegatedStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.<>n1(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketConnectionStream.d22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.WebSockets.WebSocketBase.d48.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at System.Net.WebSockets.WebSocketBase.WebSocketOperation.d19.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.WebSockets.WebSocketBase.d47.MoveNext() at System.Net.WebSockets.WebSocketBase.ThrowIfConvertibleException(String methodName, Exception exception, CancellationToken cancellationToken, Boolean aborted) at System.Net.WebSockets.WebSocketBase.d47.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.DefaultClientWebSocket.d12.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.WebSocketTransport.d36.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Transport.WebSocketTransport.d37.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Routers.WebSocketRouter.d7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.Routers.Router.d49.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.SocketIO.d102.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at SocketIOClient.SocketIO.d__101.MoveNext()<---

Jakobi-mirsk commented 2 years ago

just to clarify. The error only happens to some of the connections

doghappy commented 2 years ago

Thank you for your feedback.

I tried the following code, but it cannot be reproduced. Can you help me improve it? thanks

SocketIOClient: 3.0.4 socket.io(server): 4.1.2

static async Task Main(string[] args)
{
    var uri = new Uri("http://localhost:11004/");

    for (int i = 0; i < 100; i++)
    {
        var socket = new SocketIO(uri);
        socket.OnConnected += Socket_OnConnected;

        socket.On("hi", response =>
        {
            Console.WriteLine(response.GetValue<string>());
        });

        await socket.ConnectAsync();
    }

    Console.ReadLine();
}

private static async void Socket_OnConnected(object sender, EventArgs e)
{
    Console.WriteLine("Socket_OnConnected");
    var socket = sender as SocketIO;
    Console.WriteLine("Socket.Id:" + socket.Id);
    int i = 0;
    while (true)
    {
        i++;
        await socket.EmitAsync("hi", i.ToString());
        await Task.Delay(300);
    }
}
Jakobi-mirsk commented 2 years ago

Maybe I am doing it wrong, but this is my send method, it alerts me when sending is too slow. So i start at timer before i send and when the send routine is done I check how long it took and i also have some error handling in there:

public async void Send(string eventName, object request)
{
    if (socket == null || faulted)
        return;
    Stopwatch sendTimer = new Stopwatch();
    sendTimer.Start();

    await socket.EmitAsync(eventName, request).
        ContinueWith(new Action<Task>((task) => {
            if (task.IsFaulted)
            {
                lock (lockobj)
                {
                    if (!faulted)
                    {
                        faulted = true;
                        Log("Failed to send, task faulted", LogType.Error, task.Exception);
                        if (OnError != null)
                            Task.Factory.StartNew(() => { OnError(GetContextId()); });
                    }
                }
            }

            if (sendTimer.IsRunning)
            {
                sendTimer.Stop();
                if (sendTimer.ElapsedMilliseconds >= 5000)
                {
                    Console.WriteLine("Too slow");
                }
            }
        }));
}