简体   繁体   English

.NET Core:WebClient 中的并发缺陷?

[英].NET Core: Concurrency defect in WebClient?

I use this code to hammer on a system:我使用这段代码来敲击系统:

WebClient client = new WebClient();
int i = 0;
int limit = 10000;
long start = DateTime.Now.Ticks;

do
{
    Console.WriteLine($"{DateTime.Now:h:mm:ss.fffffff} : " + ++i);
    client.DownloadString("https://localhost:44305/");
} while (i < limit);

Console.WriteLine(limit + " requests in " + new TimeSpan(DateTime.Now.Ticks - start) + " (" + ((DateTime.Now.Ticks - start)/limit)/1000 + " ms/request)");

Sometimes it works.有时它会起作用。 Sometimes I get an exception (iteration number seems random):有时我会遇到异常(迭代次数似乎是随机的):

System.Net.WebException: Only one usage of each socket address (protocol/network address/port) is normally permitted. Only one usage of each socket address (protocol/n
etwork address/port) is normally permitted.
 ---> System.Net.Http.HttpRequestException: Only one usage of each socket address (protocol/network address/port) is normally permitted.
 ---> System.Net.Sockets.SocketException (10048): Only one usage of each socket address (protocol/network address/port) is normally permitted.
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at System.Net.HttpWebRequest.SendRequest()
   at System.Net.HttpWebRequest.GetResponse()
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at System.Net.WebClient.GetWebResponse(WebRequest request)
   at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream)
   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   at System.Net.WebClient.DownloadString(Uri address)
   at CommandName.ThingDoer.DoThing(IRepository repository) in C:\data\OneDrive\source\rider\ContentstackPlaygroundTemplates\cstest\ThingDoer.cs:line 31
   at CommandName.Program.<>c__DisplayClass0_1.<Main>b__0() in C:\data\OneDrive\source\rider\ContentstackPlaygroundTemplates\cstest\Program.cs:line 65
   at McMaster.Extensions.CommandLineUtils.CommandLineApplicationExtensions.<>c__DisplayClass9_0.<OnExecute>b__0()
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass144_0.<OnExecute>b__0(CancellationToken _)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.ExecuteAsync(String[] args, CancellationToken cancellationToken)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
   at CommandName.Program.Main(String[] args) in C:\data\OneDrive\source\rider\ContentstackPlaygroundTemplates\cstest\Program.cs:line 70 : Only one usage of each socket address (protocol/network address/port) is normally permitted. Only one usage of each socket address (protocol/network address/port) is normally permitted.

Could this be a concurrency defect in WebClient, am I doing something wrong, or what could be the explanation?这可能是 WebClient 中的并发缺陷,我做错了什么,或者可能是什么解释?

System.Web.Client 4.0.2.0, .NETCoreApp v3.0.3 System.Web.Client 4.0.2.0,.NETCoreApp v3.0.3

Thank you.谢谢你。 I did not try with ServicePointManager because HttpClient seemed to solve the issue.我没有尝试使用 ServicePointManager,因为 HttpClient 似乎解决了这个问题。 This seems to work now.这似乎现在有效。

private void McHammer()
{
    int i = 0;
    int limit = 1000;
    DateTime start = DateTime.Now;

    HttpClient httpClient = new HttpClient();
    do
    {
        try
        {
            if (i % 100 == 0)
            {
                Console.Write("#");
            }

            string discard = httpClient.GetStringAsync("https://localhost:5001/").Result;
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine(ex.GetType() + " : " + ex.Message);
            // break on first error
            limit = 0;
        }
    } while (i++ < limit);

        TimeSpan timeSpan = new TimeSpan(DateTime.Now.Ticks - start.Ticks);
        double ms = timeSpan.Ticks / 10000;
        double msPerRequest = ms / --i;
        double requestPerSec = i / ms;
        Console.WriteLine(
            "{0} : {1} requests in {2}ms ({3} ~ms/request; ~{4} request/sec)",
            this,
            i,
            ms,
            Math.Round(msPerRequest * 1000)/1000,
            Math.Round(requestPerSec * 1000));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM