Проверка прокси-серверов одновременно


Я пытаюсь проверить правильность несколько тысяч публичных прокси-серверы быстро. Для этого я посылаю веб-запросы через каждый прокси для веб-сайта, такие как example.com и проверив, что нет таких ошибок, как происходит тайм-ауты, и что страница содержит определенное строковое значение, которое я уже знаю, что сайт будет содержать.

С помощью синхронного метода, как класса HttpWebRequest.GetResponse и просто не будет делать для моего большого списка. Так я с помощью класса HttpWebRequest.Вместо BeginGetResponse, и проходя в объект действия, называемого обратного вызова и вызова, что обратного вызова, после завершения или отклонения запроса.

Я хочу знать, если есть лучший путь для достижения параллелизма, которые мне нужны. С Помощью Класса HttpWebRequest.GetResponseAsync фактически не уменьшают время, которое требуется, чтобы проверить весь список, хотя он не будет блокировать поток пользовательского интерфейса по сравнению к GetResponse.

Я не реализована проверка вводимых значений на некоторые классы, так что не обращайте внимания, что при ответе. Я тоже еще не добавил чек timeout с помощью класса ThreadPool.Метода registerwaitforsingleobject еще, наплевательское, что, как хорошо.

namespace HelperLib
{
    public class Proxy
    {
        public string IP { get; set; }
        public int Port { get; set; }
        public bool IsValid { get; set; }

        public Proxy(string ip, int port)
        {
            //TODO Validate input.
            this.IP = ip;
            this.Port = port;
        }

        public void TestValidityAsync(ProxyTest test, Action<bool, Exception> callback)
        {
            var request = HttpWebRequest.Create(test.URL);
            request.Proxy = new WebProxy(this.ToString());
            WebUtility.GetResponseAsync(request, (requestState, ex) => {
                if (requestState.response != null && requestState.responseString.Contains(test.Validation))
                {           
                    if (test.Invalidation == null)
                    {
                        callback.Invoke(true, ex);
                    }
                    else
                    {
                        if (!requestState.responseString.Contains(test.Invalidation))
                        {
                            callback.Invoke(true, ex);
                        }
                        else
                        {
                            callback.Invoke(false, ex);
                        }
                    }
                }
                else
                {
                    callback.Invoke(false, ex);
                }
            });
        }

        public override string ToString()
        {
            return this.IP + ":" + this.Port;
        }

    }
}

namespace HelperLib
{
    public class ProxyTest
    {
        public string URL { get; set; }
        public string Validation { get; set; }
        public string Invalidation { get; set; }

        public ProxyTest(string url, string validation)
        {
            this.URL = url;
            this.Validation = validation;
        }

        public ProxyTest(string url, string validation, string invalidation)
        {
            this.URL = url;
            this.Validation = validation;
            this.Invalidation = invalidation;
        }
    }
}
namespace HelperLib
{
    public class WebUtility
    {

        public static void GetResponseAsync(WebRequest request, Action<RequestState, Exception> callback)
        {
            //Send a non-blocking asynchronous web request.
            var requestState = new RequestState();
            requestState.request = request;
            requestState.responseCallback = callback;
            requestState.request.BeginGetResponse(new AsyncCallback(ResponseCallback), requestState);
        }

        private static async void ResponseCallback(IAsyncResult ar)
        {
            var requestState = (RequestState)ar.AsyncState;
            try
            {
                requestState.response = requestState.request.EndGetResponse(ar);
                requestState.responseStream = requestState.response.GetResponseStream();
                using (var sr = new StreamReader(requestState.responseStream))
                {
                    requestState.responseString = await sr.ReadToEndAsync();
                }
                requestState.responseCallback.Invoke(requestState, null);
            }
            catch (Exception ex)
            {
                requestState.responseCallback.Invoke(requestState, ex);
            }
        }

    }
}

namespace HelperLib
{
    public class RequestState
    {
        public WebRequest request;
        public WebResponse response;
        public Action<RequestState, Exception> responseCallback;
        public StringBuilder responseBuilder = new StringBuilder();
        public Stream responseStream;
        public Byte[] responseBuffer = new Byte[1024];
        public string responseString;
    }
}

Сравнение скорости с помощью HttpClient

   private void MethodA()
    {
        ManualResetEvent mre = new ManualResetEvent(false);
        Stopwatch sw = Stopwatch.StartNew();
        ServicePointManager.DefaultConnectionLimit = 500;
        int responseCount = 0;
        for (int i = 0; i < iterations; i++)
        {
            WebRequest req = WebRequest.Create("http://example.com");
            HelperLib.WebUtility.GetResponseAsync(req, (requestState, ex) =>
            {
                responseCount++;
                if (responseCount == iterations)
                {
                    mre.Set();
                }
            });
        }
        mre.WaitOne();
        Debug.WriteLine(sw.ElapsedMilliseconds);
        //Outputs 816
    }

    private async void MethodB()
    {
        Stopwatch sw = Stopwatch.StartNew();
        using (HttpClient client = new HttpClient())
        {
            for (int i = 0; i < iterations; i++)
            {
                string response = await client.GetStringAsync("http://example.com");
            }
        }
        sw.Stop();
        Debug.WriteLine(sw.ElapsedMilliseconds);
        //Outputs 2744
    }


Комментарии
1 ответ

Рассмотрим ниже на примере изначально предусмотрено

static HttpClient client = new HttpClient();
private async Task MethodB() {
Stopwatch sw = Stopwatch.StartNew();
List<Task<string>> tasks = new List<Task<string>>();
for (int i = 0; i < iterations; i++) {
var task = client.GetStringAsync("http://example.com");
tasks.Add(task);
}
var responses = await Task.WhenAll(tasks);
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
}

HttpClient должны быть созданы один раз и используется в течение всего жизненного цикла приложения.

Избежать async void функции. Вместо того, чтобы их вернуть Task.

Задачи могут быть выполнены одновременно с использованием Task.WhenAll.

Что касается масштаба, группы, запросы в управляемые партиями и выполнять их асинхронно.

Вы можете добавить токен отмены, чтобы тайм-аут любые запросы, займет больше времени, чем предопределенный срок.

Это означает, что для партии он будет идти только пока тайм-аут.

Каждый запрос может быть воплощен в его собственную функцию для обработки исключений или функциональности ответ.

1
ответ дан 3 апреля 2018 в 01:04 Источник Поделиться