Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What level of thread-safety can I expect from System.Net.Security.SslStream?

I have an application which uses SslStream to send and receive data with its own fixed-length framing. The stream is created by wrapping the NetworkStream returned from TcpClient.GetStream() like so:

var client = new TcpClient();
client.Connect(host, port);
var sslStream = new SslStream(client.GetStream(), false, callback, null);
sslStream.AuthenticateAsClient(hostname);

Because the protocol is fully asynchronous (framed "messages" arrive at arbitrary times and the client is allowed to send them at arbitrary times), I would normally spawn a thread responsible for blocking on NetworkStream.Read() and otherwise ensure that there is only one thread calling NetworkStream.Write(...) at any one time.

The Remarks section for NetworkStream says:

Read and write operations can be performed simultaneously on an instance of the NetworkStream class without the need for synchronization. As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.

However, the MSDN documentation "Thread Safety" section for SslStream says:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Because SslStream and NetworkStream aren't in the same class hierarchy, I have assumed (perhaps incorrectly) that the remarks for NetworkStream don't apply to SslStream.

Is the best approach for thread safety to simply wrap SslStream.BeginRead / SslStream.EndRead and SslStream.BeginWrite / SslStream.EndWrite with something like this?

internal sealed class StateObject
{
    private readonly ManualResetEvent _done = new ManualResetEvent(false);

    public int BytesRead { get; set; }
    public ManualResetEvent Done { get { return _done; } }
}

internal sealed class SafeSslStream
{
    private readonly object _streamLock = new object();
    private readonly SslStream _stream;

    public SafeSslStream(SslStream stream)
    {
        _stream = stream;
    }

    public int Read(byte[] buffer, int offset, int count)
    {
        var state = new StateObject();
        lock (_streamLock)
        {
             _stream.BeginRead(buffer, offset, count, ReadCallback, state);
        }
        state.Done.WaitOne();
        return state.BytesRead;
    }

    public void Write(byte[] buffer, int offset, int count)
    {
        var state = new StateObject();
        lock (_streamLock)
        {
            _stream.BeginWrite(buffer, offset, count, WriteCallback, state);
        }
        state.Done.WaitOne();
    }

    private void ReadCallback(IAsyncResult ar)
    {
        var state = (StateObject)ar.AsyncState;
        lock (_streamLock)
        {
            state.BytesRead = _stream.EndRead(ar);
        }
        state.Done.Set();
    }

    private void WriteCallback(IAsyncResult ar)
    {
        var state = (StateObject)ar.AsyncState;
        lock (_streamLock)
        {
            _stream.EndWrite(ar);
        }
        state.Done.Set();
    }
}
like image 590
Hunter Morris Avatar asked Nov 01 '11 16:11

Hunter Morris


People also ask

Is .NET queue thread-safe?

Net acts as a thread safe FIFO based generic queue. The following is the list of the important methods in the ConcurrentQueue<T> class. TryPeek(out T) - this method is used to retrieve the next element from the queue but it doesn't remove the element from the queue.

What is thread safety in C#?

A piece of code or data structure is thread safe, when the outcome of the code and underlying resources do not create undesirable results (inconsistent data, exception etc.), because of multiple threads interacting with the code concurrently. That simply means: All threads behave properly.

What is Sslstream?

Provides a stream used for client-server communication that uses the Secure Socket Layer (SSL) security protocol to authenticate the server and optionally the client.

How do you make a method thread-safe in C#?

So friends this just an example to make you understand why it is necessary to make thread as Thread Safe in Csharp. In order to make a thread as thread safe there are some thread synchronization techniques like Monitor/Lock, Mutex, Semaphore and SemaphoreSlim using these techniques we can achieve Thread Safety.


1 Answers

The phrase you pulled from the MSDN docs is a catch-all that is placed in the documentation of most classes. If a member's documentation explicitly states thread safety (as NetworkStream does) then you can rely on it.

However, what they are stating is that you can perform one read and one write at the same time, not two reads or two writes. As such, you will need to synchronise or queue your reads and writes separately. Your code looks sufficient to do this.

like image 188
Polynomial Avatar answered Nov 15 '22 00:11

Polynomial