本文介绍了关闭所有底层网络连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:
我有一个连接到服务器获取数据的一些code。然而,在某些时候程序钻进的状态下,它被未连接到服务器。我们看到的问题是,服务器不断地超时,当我们尝试重新连接。

Background:
I have some code that is connecting to a server to pull data. However, at some point the program got into a state where it was failing to connect to the server. The problem we were seeing is that the server was continually timing out when we were attempting to reconnect.

插件:
我们有自己的超时设置为使用我们的网络插件(一个节俭的插件)的默认值。这些值是100,000毫秒超时和300K毫秒读写超时。不完全是短期超时。此外,我们每次尝试重新连接时,我们重新创建插件的类,所以任何值它的内部设置是每次我们尝试重新连接时复位。我相信超时是不是问题。我相信这个插件不是问题。

Plugin:
We have our timeout set to the default values used by our network plugin (a Thrift plugin). These values are 100k millisecond timeout and 300k millisecond readwrite timeout. Not exactly short timeouts. Also, every time we attempt to reconnect, we recreate the plugin's class, so whatever values it's setting internally are reset each time we attempt to reconnect. I believe timeouts are not the issue. And I believe the plugin is not the issue.

网络:
我们看到这些反复发生超时半小时。当我们重新启动该服务(而不是机器),它立即就重新联机。所以,我知道这是不是网络的问题。这使我相信它的东西,在我们的code,它正在进入一个无效的网络状态。此外,这是我们无法控制的,因为我们的插件隐藏所有从我们的良好的网络东西的状态 - 包括超时,保持活动标志和连接组(其中包括)。我们基本上没有进入HTTPWebReqest成员。

Network:
We saw these repeated timeouts occur for half an hour. When we restarted the service (not the machine), it immediately came back online. So, I know it wasn't a network issue. That leads me to believe it's something in our code that is getting into an invalid network state. Also, it is a state that we can't control, since our plugin hides all of the good network stuff from us--including timeouts, keepalive flags, and connection groups (among others). We basically don't have access to the HTTPWebReqest member.

问:
当我们的网络设置进入这种状态下,我们试图关闭所有连接并重新连接到服务器。我们的目标是杀死,以恢复我们进入任何状态的所有活动连接。然而,当我们尝试重新连接,我们正在对我们的重新连接超时。

Question:
When our network settings get into this state, we attempt to close all connections and reconnect to the server. The goal was to kill all the active connections in order to reset whatever state we got into. However, when we attempt to reconnect, we're getting timeouts on our reconnect.

不知何故(可能是由于Keepalive与TCP流水线,这是我们无法控制),网络连接保持打开状态,即使我们已经关闭了所有连接。这让我们在一个糟糕的状态和prevents我们从骑自行车到服务器,我们之间的联系。

Somehow (probably due to the KeepAlive and TCP Pipelining, which we can't control), the network connections remain open even though we have closed all connections. This leaves us in a bad state and prevents us from cycling our connections to the server.

的问题:
我如何能杀死所有底层连接到服务器,以迫使重新连接?

The question:
How can I kill all underlying connections to a server in order to force a reconnect?

推荐答案

基础.NET架构将保持,以改善整体网络性能的连接(经由的KeepAlive)。最简单的解决方法就是设置的KeepAlive为false,在所有的连接,使它们不会保持这些无效的状态。缺点是,你会增加您的流量,因为他们将不得不每次都重新建立连接。

The underlying .Net architecture will maintain the connection (via the KeepAlive) in order to improve overall network performance. The easiest solution is to just set the KeepAlive to false on all your connections so that they will not maintain those invalid states. The downside is that you'll increase your traffic since they will have to re-establish connections every time.

此外,由于你的没有进入保活的(或HttpWebRequest对象),你必须要找到一个方法来杀死的要求设置外的连接。

Also, since you do not have access to the keepalive (or the HTTPWebRequest object), you'll have to find a way to kill the connections outside of the request settings.

有两种方法,你可以得到净释放这些连接。他们都涉及到越来越下降到的ServicePoint水平和处理相连接。

There are two approaches you can take to get .Net to release these connections. Both of them involve getting down to the ServicePoint level and dealing with connection groups.

  1. CloseConnectionGroups

在创建HttpWebRequest的,你可以给它一个连接组。从那里,你可以使用CloseConnectionGroup()函数从的ServicePoint以杀死所有连接到该服务。

When you create your HTTPWebRequest, you can give it a connection group. From there, you can use the CloseConnectionGroup() function from the ServicePoint in order to kill all connections to that service.

ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
srvrPoint.CloseConnectionGroup(myConnGroup)

当然,如果你有多个连接组,你需要做的是为每个连接组的循环。

Of course, if you have more than one connection group, you'll need to do that in a loop for every connection group.

请注意,如果你选择了这条路,要小心,不要把所有的连接在同一组。这可能会导致你用完插座。 这里更多信息。

Note that if you choose this path, be careful not to put all connections in the same group. This could cause you to run out of sockets. More information here.

ReleaseAllConnectionGroups

还有就是的ServicePoint类中的内部函数可以调用,将杀死所有连接到为服务点(即服务器)。然而,因为它是内部的类,你将不得不使用反射来得到它:

There is an internal function within the ServicePoint class that you can call that will kill all connections to the give service point (ie server). However, because it's internal to the class, you'll have to use reflection to get at it:

    ServicePoint srvrPoint = ServicePointManager.FindServicePoint(serverUri);
    MethodInfo ReleaseConns = srvrPoint.GetType().GetMethod
            ("ReleaseAllConnectionGroups",
            BindingFlags.Instance | BindingFlags.NonPublic);
    ReleaseConns.Invoke(srvrPoint, null);

这code只翻出从ServerPoint的ReleaseAllConnectionGroups和不带参数调用它。该功能将通过所有的连接组织在其内部列表,并释放所有的资源 - 杀死所有的连接

This code just pulls out the ReleaseAllConnectionGroups from that ServerPoint and invokes it with no parameters. This function will go through all connection groups in its internal list and release all of those resources--killing all of the connections.

帝国的毁灭:因为这是一个私人会员,你不能保证它会在那里,如果你升级你的.Net版本。这是目前在版本2.0到4.5可用,但。链接到 ReleaseAllConnectionGroups的逆向工程code 的。

Downfall: Because this is a private member, you're not guaranteed that it will be there if you upgrade your version of .Net. It's currently available in versions 2.0 through 4.5, though. A link to the reverse engineered code of ReleaseAllConnectionGroups.

由于您不能设置连接组,你将不得不使用选项2。

Because you cannot set the connection group, you will have to use option 2.

不幸的是,有没有其他的方法来获取.NET关闭那些低级别的连接,而不设置keepalive标记释放自己的KeepAlive状态。

Unfortunately, there's no other way to get .Net to close those low-level connections and release their KeepAlive status without setting the KeepAlive flag.

这篇关于关闭所有底层网络连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 04:55