Ole*_*nko 7 c# proxy httpclient
我对某些资源执行了很多请求HttpClient。为了避免舔,我将其用作单个实例。类似的东西......我想使用代理,那么如何为每个请求使用不同的代理?
谢谢!
public class Program
{
private static HttpClient Client = new HttpClient();
public static void Main(string[] args)
{
Console.WriteLine("Starting connections");
for(int i = 0; i<10; i++)
{
var result = Client.GetAsync("http://aspnetmonsters.com").Result;
Console.WriteLine(result.StatusCode);
}
Console.WriteLine("Connections done");
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
啊,我看错问题了。
它不是关于如何将随机 IWebProxy 与 HttpClientHandler 一起使用,而是如何解决在第一个请求开始后无法重置同一 HttpClientHandler 的代理属性的问题。
问题是您无法重置 HttpClientHandler 的代理...
System.InvalidOperationException: '此实例已启动一个或多个请求。
只能在发送第一个请求之前修改属性。
但这仍然相当容易。
执行:
public class WebProxyService
: System.Net.IWebProxy
{
protected System.Net.IWebProxy m_proxy;
public System.Net.IWebProxy Proxy
{
get { return this.m_proxy ??= System.Net.WebRequest.DefaultWebProxy; }
set { this.m_proxy = value; }
}
System.Net.ICredentials System.Net.IWebProxy.Credentials
{
get { return this.Proxy.Credentials; }
set { this.Proxy.Credentials = value; }
}
public WebProxyService()
{ } // Constructor
public WebProxyService(System.Net.IWebProxy proxy)
{
this.Proxy = proxy;
} // Constructor
System.Uri System.Net.IWebProxy.GetProxy(System.Uri destination)
{
return this.Proxy.GetProxy(destination);
}
bool System.Net.IWebProxy.IsBypassed(System.Uri host)
{
return this.Proxy.IsBypassed(host);
}
}
Run Code Online (Sandbox Code Playgroud)
然后用法如下:
public class AlternatingProxy
{
public static async System.Threading.Tasks.Task Test()
{
string url = "http://aspnetmonsters.com";
System.Net.WebProxy[] proxies = new[] {
null,
new System.Net.WebProxy("104.238.172.20", 8080),
new System.Net.WebProxy("104.238.167.193", 8080),
new System.Net.WebProxy("136.244.102.38", 8080),
new System.Net.WebProxy("95.179.202.40", 8080)
};
System.Random rnd = new System.Random();
WebProxyService proxyService = new WebProxyService();
using (System.Net.Http.HttpClient hc = new System.Net.Http.HttpClient(
new System.Net.Http.HttpClientHandler { UseProxy = true, Proxy = proxyService }
))
{
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
hc.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148");
hc.DefaultRequestHeaders.Add("Accept-Language", "fr-FR, fr;q=0.9, en;q=0.8, it;q=0.7, *;q=0.5");
hc.DefaultRequestHeaders.Add("Referer", "https://www.baidu.com");
hc.DefaultRequestHeaders.ConnectionClose = true;
for (int i = 0; i < 10; ++i)
{
proxyService.Proxy = proxies[rnd.Next(proxies.Length)];
string response = await hc.GetStringAsync(url);
}
}
} // End Task Test
} // End Class TestMe
Run Code Online (Sandbox Code Playgroud)
如果你想使用单例,也许这是一个想法:
公共类WebProxyService:System.Net.IWebProxy {
protected System.Net.IWebProxy m_proxy;
public System.Net.IWebProxy Proxy
{
get { return this.m_proxy ??= System.Net.WebRequest.DefaultWebProxy; }
set { this.m_proxy = value; }
}
System.Net.ICredentials System.Net.IWebProxy.Credentials
{
get { return this.Proxy.Credentials; }
set { this.Proxy.Credentials = value; }
}
public WebProxyService()
{ } // Constructor
public WebProxyService(System.Net.IWebProxy proxy)
{
this.Proxy = proxy;
} // Constructor
protected System.Func<System.Net.WebProxy>[] proxies = new System.Func<System.Net.WebProxy>[] {
delegate(){ return new System.Net.WebProxy("104.238.172.20", 8080); },
delegate (){ return new System.Net.WebProxy("104.238.167.193", 8080);},
delegate(){ return new System.Net.WebProxy("136.244.102.38", 8080);},
delegate(){ return new System.Net.WebProxy("95.179.202.40", 8080);}
};
System.Uri System.Net.IWebProxy.GetProxy(System.Uri destination)
{
return proxies[RandomGen2.Next(proxies.Length)]().GetProxy(destination);
}
bool System.Net.IWebProxy.IsBypassed(System.Uri host)
{
return this.Proxy.IsBypassed(host);
}
private static class RandomGen2
{
private static System.Random _global = new System.Random();
[System.ThreadStatic]
private static System.Random _local;
public static int Next(int maxValue)
{
System.Random inst = _local;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_local = inst = new System.Random(seed);
}
return inst.Next(maxValue);
}
}
} // End Class WebProxyService
Run Code Online (Sandbox Code Playgroud)
如果更改代理,它仍然不是线程安全的。
因此,使用固定的不可变代理列表并阻止设置属性。
这样,它应该是线程安全的。
public class WebProxyService
: System.Net.IWebProxy
{
protected System.Net.IWebProxy[] m_proxyList;
public System.Net.IWebProxy Proxy
{
get
{
// https://devblogs.microsoft.com/pfxteam/getting-random-numbers-in-a-thread-safe-way/
if (this.m_proxyList != null)
return this.m_proxyList[ThreadSafeRandom.Next(this.m_proxyList.Length)];
return System.Net.WebRequest.DefaultWebProxy;
}
set
{
throw new System.InvalidOperationException("It is not thread-safe to change the proxy-list.");
}
}
System.Net.ICredentials System.Net.IWebProxy.Credentials
{
get { return this.Proxy.Credentials; }
set { this.Proxy.Credentials = value; }
}
public WebProxyService()
{
} // Constructor
public WebProxyService(System.Net.IWebProxy[] proxyList)
{
this.m_proxyList = proxyList;
} // Constructor
System.Uri System.Net.IWebProxy.GetProxy(System.Uri destination)
{
return this.Proxy.GetProxy(destination);
}
bool System.Net.IWebProxy.IsBypassed(System.Uri host)
{
return this.Proxy.IsBypassed(host);
}
} // End Class WebProxyService
Run Code Online (Sandbox Code Playgroud)
在 ASP.NET-Core 中使用 HttpClient 代理实际上非常简单。
您需要做的就是在 HttpClient 构造函数中设置处理程序。
然后为每个请求设置处理程序的代理属性。
像这样:
public class Program
{
public static async System.Threading.Tasks.Task Main(string[] args)
{
string url = "http://aspnetmonsters.com";
System.Net.WebProxy[] proxies = new[] {
null,
new System.Net.WebProxy("104.238.172.20", 8080),
new System.Net.WebProxy("104.238.167.193", 8080),
new System.Net.WebProxy("136.244.102.38", 8080),
new System.Net.WebProxy("95.179.202.40", 8080)
};
System.Random rnd = new System.Random();
using (System.Net.Http.HttpClientHandler handler = new System.Net.Http.HttpClientHandler()
{
Proxy = new System.Net.WebProxy("http://127.0.0.1:8888"),
UseProxy = true,
})
{
using (System.Net.Http.HttpClient hc = new System.Net.Http.HttpClient(handler))
{
System.Console.WriteLine("Starting connections");
for (int i = 0; i < 10; i++)
{
handler.Proxy = proxies[rnd.Next(proxies.Length)];
await hc.GetAsync(url);
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
hc.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148");
hc.DefaultRequestHeaders.Add("Accept-Language", "fr-FR, fr;q=0.9, en;q=0.8, it;q=0.7, *;q=0.5");
hc.DefaultRequestHeaders.Add("Referer", "https://www.baidu.com");
using (System.Net.Http.HttpResponseMessage response = await hc.GetAsync(url))
{
// using (var fs = new System.IO.MemoryStream())
// { await response.Content.CopyToAsync(fs); }
byte[] ba = await response.Content.ReadAsByteArrayAsync();
} // End Using response
} // Next i
System.Console.WriteLine("Ending connections");
} // End Using hc
} // End Using handler
System.Console.WriteLine("--- Press any key to continue --- ");
System.Console.ReadKey();
} // End Task Main
} // End Class Program
Run Code Online (Sandbox Code Playgroud)
Nic*_*los -1
因此,基本上,为了能够更改代理,您将需要HttpClientHandler.
可以在这里找到一个简单的示例:C# use proxy with HttpClient request
和另一个示例:Simple C# .NET 4.5 HTTPClient Request using Basic Auth and Proxy
我建议将其保留HttpClientHandler在私有字段中,并在每次需要时使用引用来更改代理。
但请记住,如果您需要同时使用不同的代理,则需要拥有该类的多个实例HttpClientHandler。
如果您需要我为此制作示例代码。平我。
谢谢。