chronoxor / NetCoreServer

Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
https://chronoxor.github.io/NetCoreServer
MIT License
2.63k stars 550 forks source link

TcpSession.SendAsync() returns true even if a message fails to send. BytesSent also increases when send fails. #299

Open crav12345 opened 3 months ago

crav12345 commented 3 months ago

In an instance where my server is told to send multiple TCP messages from the main thread on the same clock tick, the lock statement in SendAsync() appears to prevent the second message from sending. However, the method still returns true when the second message fails to send. Spacing out the SendAsync() calls allows the second message to send, but is there a way to determine whether a message actually sends for cases where the lock blocks one? That way, I could just try to send the message until it successfully sends or until I say to stop trying.

I tried doing this with BytesSent, but the value appears to increase even in these cases where the message doesn't actually send. I don't know if this is a bug or me using the method incorrectly.

NetCoreServer.TcpSession

public virtual bool SendAsync(ReadOnlySpan<byte> buffer)
{
    if (!IsConnected)
    {
        return false;
    }

    if (buffer.IsEmpty)
    {
        return true;
    }

    // ----------------------------------------------------------------------------------------
    // Prevents second message from sending on same tick. Method still returns true.
    // ----------------------------------------------------------------------------------------
    lock (_sendLock)
    {
        if (_sendBufferMain.Size + buffer.Length > OptionSendBufferLimit && OptionSendBufferLimit > 0)
        {
            SendError(SocketError.NoBufferSpaceAvailable);
            return false;
        }

        _sendBufferMain.Append(buffer);
        BytesPending = _sendBufferMain.Size;
        if (_sending)
        {
            return true;
        }

        _sending = true;
        TrySend();
    }

    return true;
}