我有一个应用程序,它使用SslStream
自己的固定长度帧发送和接收数据。流是通过像这样包装NetworkStream
返回的来创建的TcpClient.GetStream()
:
var client = new TcpClient();
client.Connect(host, port);
var sslStream = new SslStream(client.GetStream(), false, callback, null);
sslStream.AuthenticateAsClient(hostname);
因为协议是完全异步的(框架“消息”在任意时间到达,客户端可以在任意时间发送它们),我通常会生成一个负责阻塞的线程NetworkStream.Read()
,否则确保只有一个线程NetworkStream.Write(...)
在任何时候调用一度。
备注部分NetworkStream
说:
可以在 NetworkStream 类的实例上同时执行读取和写入操作,而无需同步。只要写操作有一个唯一线程,读操作有一个唯一线程,读写线程之间就不会相互干扰,也不需要同步。
但是,MSDN 文档“线程安全”部分SslStream
说:
此类型的任何公共静态(在 Visual Basic 中为 Shared)成员都是线程安全的。不保证任何实例成员都是线程安全的。
因为SslStream
和NetworkStream
不在同一个类层次结构中,所以我假设(可能是错误的) 的注释NetworkStream
不适用于SslStream
.
线程安全的最佳方法是简单地用这样的东西包装SslStream.BeginRead
/SslStream.EndRead
和SslStream.BeginWrite
/吗?SslStream.EndWrite
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();
}
}