Ric*_*ard 9 .net c# sockets network-programming
背景:
我有一些代码连接到服务器来提取数据.但是,在某些时候程序进入了无法连接到服务器的状态.我们看到的问题是,当我们尝试重新连接时,服务器不断超时.
插件:
我们将超时设置为我们的网络插件(Thrift插件)使用的默认值.这些值是100k毫秒超时和300k毫秒读写超时.不完全是短暂的超时.此外,每次我们尝试重新连接时,我们都会重新创建插件的类,因此无论每次我们尝试重新连接时,内部设置的值都会重置.我认为超时不是问题.我相信插件不是问题.
网络:
我们看到这些重复超时发生了半个小时.当我们重新启动服务(而不是机器)时,它立即重新上线.所以,我知道这不是一个网络问题.这让我相信我们的代码中的某些内容正在进入无效的网络状态.此外,这是一个我们无法控制的状态,因为我们的插件隐藏了我们所有的好网络内容 - 包括超时,保持标记和连接组(以及其他).我们基本上无法访问HTTPWebReqest成员.
问题:
当我们的网络设置进入此状态时,我们会尝试关闭所有连接并重新连接到服务器.目标是杀死所有活动连接,以便重置我们进入的状态.但是,当我们尝试重新连接时,我们的重新连接会超时.
不知何故(可能是由于KeepAlive和TCP Pipelining,我们无法控制),即使我们关闭了所有连接,网络连接仍保持打开状态.这使我们处于不良状态并阻止我们将连接循环到服务器.
问题:
我如何杀死服务器的所有底层连接以强制重新连接?
Ric*_*ard 10
底层.Net架构将维护连接(通过KeepAlive),以提高整体网络性能.最简单的解决方案是在所有连接上将KeepAlive设置为false,以便它们不会保持这些无效状态.缺点是你会增加流量,因为他们每次都必须重新建立连接.
此外,由于您无权访问keepalive(或HTTPWebRequest对象),因此您必须找到一种方法来终止请求设置之外的连接.
有两种方法可以让.Net发布这些连接.它们都涉及到ServicePoint级别和处理连接组.
CloseConnectionGroups
创建HTTPWebRequest时,可以为其指定连接组.从那里,您可以使用ServicePoint中的CloseConnectionGroup()函数来终止与该服务的所有连接.
ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
srvrPoint.CloseConnectionGroup(myConnGroup)
Run Code Online (Sandbox Code Playgroud)
当然,如果您有多个连接组,则需要在每个连接组的循环中执行此操作.
请注意,如果选择此路径,请注意不要将所有连接放在同一组中.这可能会导致您的套接字耗尽. 更多信息在这里.
ReleaseAllConnectionGroups
ServicePoint类中有一个内部函数可以调用,它将终止与给定服务点(即服务器)的所有连接.但是,因为它是类的内部,所以你必须使用反射来实现它:
ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
MethodInfo ReleaseConns = srvrPoint.GetType().GetMethod
("ReleaseAllConnectionGroups",
BindingFlags.Instance | BindingFlags.NonPublic);
ReleaseConns.Invoke(srvrPoint, null);
Run Code Online (Sandbox Code Playgroud)
此代码只是从该ServerPoint中提取ReleaseAllConnectionGroup并在没有参数的情况下调用它.此函数将遍历其内部列表中的所有连接组,并释放所有这些资源 - 终止所有连接.
垮台:因为这是一个私人会员,如果你升级你的.Net版本,你不能保证它会在那里.但它目前在版本2.0到4.5中可用.指向ReleaseAllConnectionGroups的逆向工程代码的链接.
由于无法设置连接组,因此必须使用选项2.
不幸的是,没有其他方法可以让.Net关闭那些低级连接并释放KeepAlive状态而不设置KeepAlive标志.
归档时间: |
|
查看次数: |
4493 次 |
最近记录: |