0

我正在连接到第 3 方服务器。我现在知道他们允许来自同一个远程用户的 8 个连接。但是我不知道他们是否会提高或降低连接限制。所以我希望我的应用程序能够动态找出。我怎样才能做到这一点?

我正在使用 C#,MSVS 2008

我开始为任何能给我工作 C# 的人提供赏金。如果没有人这样做,那么我会给它最好的答案。

我发现这很难做到,并且有几次失败的尝试:(

4

8 回答 8

8

这不是服务器默认提供给客户端的信息。唯一知道的方法是保持打开连接直到它失败(坏主意),或者要求服务器所有者提供您可以轮询的服务,该服务会返回此信息。

编辑:在对这个问题进行了更多思考之后,我不确定是否可以通过“探测”以任何真正的准确度来确定这一点。如果服务器503 Server Busy在达到其连接限制时返回(我假设在我提出最初的建议时会发生这种情况),那么测试会更容易。但通常当服务器超出其连接限制时,它们只是在新连接可用之前不响应。客户端只是等待响应。没有硬性方法可以区分由于已达到其连接限制而需要 10 秒响应的服务器和由于任何其他原因而需要 10 秒响应的服务器。

此外,即使您仍然尝试以这种方式对其进行测试,您对服务器发出的请求也需要保持打开足够长的时间,以确保您创建的第一个连接(以及所有后续连接)在第 n 个请求时仍然打开超时。这意味着要么调用一个需要任意长时间才能返回的服务——一个长时间运行的进程,要么调用一个 Thread.Sleep(); 或下载不方便的大文件。这两种方法充其量都是极其低效的。

于 2009-04-18T23:20:36.857 回答
2

穷人的做法是向 netstat 发送外壳,获取标准输出并检查它。它为您提供与其他计算机的当前连接的快照。由此您可以确定您连接到特定服务器的次数。

-大学教师

于 2009-04-22T14:17:56.660 回答
1

在您的情况下,更好的主意可能是不在乎。我会尝试一一打开连接并检查应用程序的性能。只要通过打开另一个连接来提高性能,就继续打开新的连接。当性能停止增加时,您将合理地接近最佳连接数。

于 2009-04-26T13:51:00.703 回答
1

我会接受这个赏金的好先生。不完全确定您为什么要这样做以及为什么有人允许 8 个连接。

定义于 1999 年 (RFC 2616) “使用持久连接的客户端应该限制他们维护到给定服务器的同时连接的数量。单用户客户端不应与任何服务器或代理保持超过 2 个连接。一个代理应该使用最多 2*N 个连接到另一个服务器或代理,其中 N 是同时活跃的用户数。这些指南旨在改善 HTTP 响应时间并避免拥塞。” 由于开发人员正在使用 AJAX 或类似 AJAX 的请求来更新网页,因此越来越多地讨论了 http 限制。

正如 RFC 所说,我只能获得 2 个与 Web 服务器的开放连接。

但这里的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;

namespace ConnectionTest
{
    public class RequestCounter
    {
        public int Counter = 0;
        public void Increment()
        {
            Interlocked.Increment(ref Counter);
        }
    }

    public class RequestThread
    {
        public AutoResetEvent AsyncWaitHandle { get; private set; }
        public RequestCounter RequestCounter;
        public String Url;
        public HttpWebRequest Request;
        public HttpWebResponse Response;

        public RequestThread(AutoResetEvent r, String u, RequestCounter rc)
        {
            Url = u;
            AsyncWaitHandle = r;
            RequestCounter = rc;
        }

        public void Close()
        {
            if (Response != null)
                Response.Close();

            if (Request != null)
                Request.Abort();
        }
    }

    public class ConnectionTest
    {
        static void Main()
        {
            string url = "http://www.google.com/";
            int max = GetMaxConnections(25, url);
            Console.WriteLine(String.Format("{0} Max Connections to {1}",max,url));
            Console.ReadLine();
        }

        private static int GetMaxConnections(int maxThreads, string url)
        {
            RequestCounter requestCounter = new RequestCounter();

            List<RequestThread> threadState = new List<RequestThread>();
            for (int i = 0; i < maxThreads; i++)
                threadState.Add(new RequestThread(new AutoResetEvent(false), url, requestCounter));

            List<Thread> threads = new List<Thread>();
            foreach (RequestThread state in threadState)
            {
                Thread t = new Thread(StartRequest);
                t.Start(state);
                threads.Add(t);
            }

            WaitHandle[] handles = (from state in threadState select state.AsyncWaitHandle).ToArray();
            WaitHandle.WaitAll(handles, 5000); // waits seconds

            foreach (Thread t in threads)
                t.Abort();

            foreach(RequestThread rs in threadState)
                rs.Close();

            return requestCounter.Counter;
        }

        public static void StartRequest(object rt)
        {
            RequestThread state = (RequestThread) rt;
            try
            {
                state.Request = (HttpWebRequest)WebRequest.Create(state.Url);
                state.Request.ReadWriteTimeout = 4000; //Waits 4 seconds

                state.Response = (HttpWebResponse)state.Request.GetResponse();
                if (state.Response.StatusDescription.Equals("OK", StringComparison.InvariantCultureIgnoreCase))
                    state.RequestCounter.Increment();

                //Do not close, or you will free a connection. Close Later
                //response.Close(); 
            }
            catch (WebException e)
            {
                //Console.WriteLine("Message:{0}", e.Message);
                state.Close();
            }
            catch (ThreadAbortException e)
            {
                //Console.WriteLine("Thread Aborted");
                state.Close();
            }
            catch(Exception e)
            {
                //Console.WriteLine("Real Exception");    
                state.Close();
            }
            finally
            {
                state.AsyncWaitHandle.Set();
            }
        }
    }
}
于 2009-04-26T14:25:07.080 回答
0

这里有一些伪代码:

connection = MakeNewConnection("ServerAddress");
while (connection.connected)
{
connectionCounter++;
connection = MakeNewConnection("ServerAddress");
}

最后,您的 connectionCounter 应该包含您可以建立的总连接数。如果您愿意,我实际上可以看到这需要什么样的 C# 代码。

PS。这对服务器来说不是一件好事,而且它可能会在一天内让你被禁止:P。

于 2009-04-18T23:21:52.627 回答
0

好吧,如果您要连接的服务器是 Windows 机器并且正在运行 WMI,那么您只需确定此信息存储在哪个注册表项中并在那里获取信息。也就是说,如果您连接的用户具有 WMI 权限。

于 2009-04-21T12:31:20.823 回答
0
int counter = 0;
while(true) {

     try{
            Open New Connection
            counter++;

        }
        catch()
        {
           Trace.WriteLine(counter);
        }
}

一定喜欢使用异常来控制流;)

于 2009-04-22T13:56:53.263 回答
0

我无法发表评论:) 但唐的回答是可靠的。根据您需要监控服务多长时间,您可以安排 netstat 将管道输出到文件,并在时间段结束时查看数据。

要清理输出数据以查看您想要的内容,可能需要结合使用 logparser 和/或 excel。

netstat 的好处是您可以消除“喋喋不休”,只看到与感兴趣的进程相关的连接(通过 pid)。

否则,您可以通过 tcpv4(或 v6)性能计数器监视使用 tcp 的服务器连接数。此连接将包括与服务器的所有连接,但您可能能够大致了解您要查找的内容。

于 2009-04-26T13:27:09.917 回答