C# 网络流在发送多条Protobuf消息时关闭
我使用protobuf net和.net的TCPClient&NetworkStream在一台服务器和多个客户端之间进行通信。对于发送消息,我在两侧使用以下方法:C# 网络流在发送多条Protobuf消息时关闭,c#,.net,protobuf-net,networkstream,C#,.net,Protobuf Net,Networkstream,我使用protobuf net和.net的TCPClient&NetworkStream在一台服务器和多个客户端之间进行通信。对于发送消息,我在两侧使用以下方法: public static bool WriteProtocolBufferToStream(System.IO.Stream stream, object protoBufObject) { // ... check parameters ...
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条)这些消息
在一段时间(几分钟到几个小时)后引发以下异常:
源代码是protobuf net的类构造函数。它引发此异常,因为NetworkStream
dest的CanWrite
属性为false。我的问题是:CanWrite
为什么在一段时间后从true变为false?这可能与缓冲区溢出有关(因为我同时发送许多消息)?我怎样才能修好它
编辑:
正如[Marc Gravell]已经指出的那样,NetworkStream
被处理,因此CanWrite
从true变为false。例如,如果我尝试访问流对象的WriteTimeout
属性,我会得到以下结果:
System.ObjectDisposedException:无法访问已处置的对象。
对象名称:“System.Net.Sockets.Socket”。
位于System.Net.Sockets.Socket.GetSocketOption(SocketOptionLevel选项级别,SocketOptionName选项名称)
在System.Net.Sockets.NetworkStream.get_WriteTimeout()中
在Utilities.CommunicationHelper.WriteProtocolBufferToStream(网络流,对象ProtoBufoObject)
...
我仍然在我的代码中寻找一些东西,这可能会导致套接字的处理。还有什么原因会导致套接字在一段时间(几个小时)后被释放?也许您正在耗尽服务器的TCP/IP端口 您没有提到您的服务器正在运行哪个操作系统,但假设它是2008年的服务器,那么您有16000个可用端口(49152-65535)。关闭连接时,端口将在再次可用之前保持4分钟的TIME_WAIT状态。这意味着,如果您在不到4分钟的时间内连接超过16000个,您的服务器将开始拒绝连接 遇到错误时,请尝试在服务器上运行以下命令:
netstat -p TCP -ano > netstat.txt
netstat.txt中的行数告诉您处于已建立或time_wait状态的TCPv4连接数
你可以调整这个。通过增加动态端口的数量、缩短等待时间间隔或两者兼而有之
要查看实际值,请执行以下操作:
- Time_wait(TcpTimedWaitDelay)(默认值为240,如果找不到该值,则为4分钟)
- 动态端口范围:
netsh int ipv4 show dynamicportrange tcp
网络流
,一点IL分析表明可以写
遵从可写
。反过来,m_Writeable
以三种方式变为false
:
- 当它被处理时
- 当使用
参数作为access
FileAccess.Read创建时
- 当
属性(可写
)被分配时(注意,我看不到框架中实际使用此属性的证据)受保护
所以:如果你说这种情况发生在一个已经建立的
网络流上,并且已经好了一段时间了,那么最有可能的答案是它在某个时候被处理掉了,可能是因为关闭了谢谢你的回答。因此,现在我必须找出NetworkStream被关闭/处置的原因。我添加了更多的日志输出,以便在新的测试运行中对此进行调查。protobuf net Dispose()是否关闭()使用NetworkStream的StreamReader或StreamWriter?根据,这将处理使用过的网络流。@Rob iirc流读写器确实关闭了底层流。从内存中看,protobuf net没有-但我必须检查以确保网络流的套接字
确实已被释放-请参见问题中的编辑。您是否查看了protobuf net中StreamReader/StreamWriter的使用情况?protobuf网络可能是导致处理的原因吗?谢谢你的回答,但它似乎与端口耗尽无关。我的机器是一台2008服务器,16384个端口中只有大约50个正在使用。我看不到端口耗尽的迹象。似乎没有任何东西指向这一点。这一信息当然没有。这不仅仅是猜测,根本不可能是原因。你没有提到它,但你在使用线程吗?只是猜测一下,因为您提供的信息有点稀疏:-)@Dag:是的,我使用线程。在当前版本中,Ilock()
方法中的所有内容。问题仍然存在。因此,这不应该是线程问题。@usr套接字的创建和处理未显示,并且在创建过程中可能会泄漏/错误处理,当通信量增加时似乎会发生错误(尽管确切的容量未知)。根据最初的问题,如何消除端口耗尽这一可能的原因?
reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\TcpTimedWaitDelay
netsh int ipv4 show dynamicportrange tcp