我使用 protobuf-net 和 .NET 的 TCPClient 和 NetworkStream 进行一台服务器和许多客户端之间的通信。对于发送消息,我在双方都使用以下方法:
public static bool WriteProtocolBufferToStream(System.IO.Stream stream, object protoBufObject)
{
// ... check parameters ...
// ... Determine the 'fieldNumber' of the 'protoBufObject' via a helper dictionary ...
if (fieldNumber > -1)
{
try { Serializer.NonGeneric.SerializeWithLengthPrefix(stream, protoBufObject, ProtoBuf.PrefixStyle.Base128, fieldNumber); }
catch (Exception ex)
{
Logger.Instance.Error("Exception: " + ex.Message);
return false;
}
}
else
{
Logger.Instance.Error("unknown message type");
return false;
}
return true;
}
在只有一些客户端和少量消息的小场景中,一切都很好。但是在大约 40 个客户端和许多交换消息的情况下,我遇到了问题。消息非常小(包含 1 到 5 个小字符串),但服务器可能会同时发送多个(最多 200 个)这些消息。
一段时间后(几分钟到几小时)会引发以下异常:
ArgumentException: Cannot write to stream. Parameter name: dest
来源是 protobuf-net 的ProtoWriter类构造函数。它抛出这个异常是因为destCanWrite
的属性是假的。我的问题是:为什么一段时间后从真变为假?是否与缓冲区溢出有关(因为我同时发送了许多消息)?我该如何解决?NetworkStream
CanWrite
编辑:
正如@[Marc Gravell] 已经指出的那样,NetworkStream
已处置,因此CanWrite
从真变为假。例如,如果我尝试访问流WriteTimeout
对象的属性,我会得到:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.GetSocketOption(SocketOptionLevel optionLevel, SocketOptionName optionName)
at System.Net.Sockets.NetworkStream.get_WriteTimeout()
at Utilities.CommunicationHelper.WriteProtocolBufferToStream(NetworkStream stream, Object protoBufObject)
...
我仍在我的代码中寻找可能导致 Socket 被丢弃的东西。一段时间(几个小时)后,还有什么可能导致 Socket 被丢弃?