我正在为传统的RPC实现开发一个客户端/服务器库,并且遇到了在等待接收到RPC请求消息的响应消息时客户端有时会挂起的问题.事实证明,真正的问题出现在我的消息框架代码中(我在从底层NetworkStream读取数据时没有正确处理消息边界),但它也让我怀疑我用来通过网络发送数据的代码,特别是在RPC服务器作为客户端RPC请求的结果向客户端发送大量数据的情况下.
我的发送代码使用BinaryWriter将完整的“消息”写入底层NetworkStream. RPC协议还实现了心跳算法,其中RPC服务器每15秒发送一次PING消息. ping是由一个单独的线程发出的,因此,至少在理论上,当服务器处于将大响应流回客户端时,可以发送ping.
假设我有一个Send方法,如下所示,其中stream是一个NetworkStream:
public void Send(Message message) { //Write the message to a temporary stream so we can send it all-at-once MemoryStream tempStream = new MemoryStream(); message.WriteToStream(tempStream); //Write the serialized message to the stream. //The BinaryWriter is a little redundant in this //simplified example,but here because //the production code uses it. byte[] data = tempStream.ToArray(); BinaryWriter bw = new BinaryWriter(stream); bw.Write(data,data.Length); bw.Flush(); }
所以我的问题是,调用bw.Write(并暗示对底层Stream的Write方法的调用)是原子的吗?也就是说,如果发送线程上仍在进行冗长的写入,并且心跳线程启动并发送PING消息,那么该线程是否会阻塞直到原始的Write调用结束,或者我是否必须向发送线程添加显式同步阻止两个发送呼叫来破坏流的方法?
解决方法
Any public static (Shared in Visual
Basic) members of this type are thread
safe. Any instance members are not
guaranteed to be thread safe.
从Stream Class起,所以不能保证.