如何诊断为什么异步TCP System.Net.Socket发送(开始/结束发送)实际上未发送任何内容?

时间:2019-06-27 16:36:17

标签: c# sockets diagnostics system.net system.net.httpwebrequest

我有一个HTTP服务器和客户端(它们都是我的代码,C#,服务器上的HttpListener和客户端上的HttpWebrequest)。

每个客户端每分钟向服务器发出大约6个HTTP请求(如果一切正常)。每个服务器最多可以有10000个客户端。服务器应在不到1秒的时间内响应。服务器逻辑很简单(没有CPU问题)。最多的代码是异步的。

在某些环境(内联网)中,一切都可以正常工作。

但是在某些Intranet环境中,大约3个POST HTTP Web请求中的1个挂起。

该问题在VMware(Win 8.1 Professional,6.3.9600 build 9600 .net 4.7.1)的单客户端计算机上明显体现

我无法在另一台计算机上复制它,也无法将该VM移至另一网络环境。因此,我需要获取一些更详细的信息。

问题在下面详细说明。就像

中所述

Async TCP System.Net.Socket send (Begin/End Send) not actually sending anything several years ago.

我已经按照Microsoft的建议从客户端和服务器那里获取了WireShark以及详细的System.Net日志。

<source name="LowLevelDesign" switchValue="Verbose">
<source name="System.Net.Http" switchValue="Verbose">
<source name="System.Net.HttpListener" switchValue="Verbose">
<source name="System.Net" switchValue="Verbose">
<source name="System.Net.Sockets" switchValue="Verbose">

来自同一套接字上客户端的多个POST HttpWebRequest可以正常工作,即日志显示请求之间的客户端端口和套接字ID相同。

我在服务器和客户端上都在Wireshark中看到所有TCP数据包都正常(服务器上的唯一警告是校验和:0xd28c不正确,应该是0xb54c(可能是由于“ TCP校验和卸载”引起的?)。

服务器对所有请求的响应大大少于1秒。

然后,在成功请求3或4个请求之后,客户端尝试发送下一个请求。

但是Wireshark中没有TCP数据包(在服务器或客户端)。由于没有看到请求,因此服务器没有任何答案。

我的代码检测到超时(10秒)而没有答案,并中止了HttpWebRequest。

然后,相同的(新的)请求在其他新的套接字(即新的客户端端口)上也可以很好地工作。但是在3-6次请求后,问题又重复了。

没有长度大于1500的消息。被挂起的请求也是短消息(标头<100字节,POST请求流数据<200字节,响应<400字节)。我看到OK和Hanged请求之间没有区别,除了OK是第一个,而Hanged是第二个,并带有100个继续。所有其他请求都没有请求数据(即request content-length == 0)。我看到带有100个继续的第二个请求始终在该环境中挂起。

由于我看到服务器在2分钟后将[RST,ACK]发送到旧套接字(旧客户端端口),因此旧连接未正确处理。而且我不知道如何优雅地关闭它。

... 
System.Net.Sockets Verbose: 0 : [6420] Data from Socket#11429296::PostCompletion
DateTime=2019-06-24T06:43:08.7370581Z
...
System.Net.Sockets Verbose: 0 : [6420] 000000A0 : 35 0D 0A 45 78 70 65 63-74 3A 20 31 30 30 2D 63 : 5..Expect: 100-c
DateTime=2019-06-24T06:43:08.7410625Z
System.Net.Sockets Verbose: 0 : [6420] Socket#11429296::EndSend(OverlappedAsyncResult#13804354)
DateTime=2019-06-24T06:43:08.7420738Z
System.Net.Sockets Verbose: 0 : [6420] Exiting Socket#11429296::EndSend()   -> Int32#187
DateTime=2019-06-24T06:43:08.7420738Z
System.Net.Sockets Verbose: 0 : [6420] Socket#11429296::UnsafeBeginReceive()
DateTime=2019-06-24T06:43:08.7420738Z
System.Net.Sockets Verbose: 0 : [6420] Exiting Socket#11429296::UnsafeBeginReceive()    -> OverlappedAsyncResult#47962264
DateTime=2019-06-24T06:43:08.7431561Z
System.Net Verbose: 0 : [5896] HttpWebRequest#52253787::EndGetRequestStream()
DateTime=2019-06-24T06:43:09.1071980Z
System.Net Verbose: 0 : [5896] Exiting HttpWebRequest#52253787::EndGetRequestStream()   -> ConnectStream#17987329
DateTime=2019-06-24T06:43:09.1081881Z
System.Net Verbose: 0 : [5896] ConnectStream#17987329::BeginWrite()
DateTime=2019-06-24T06:43:09.1081881Z
System.Net Verbose: 0 : [5896] Data from ConnectStream#17987329::BeginWrite
DateTime=2019-06-24T06:43:09.1091858Z
System.Net Verbose: 0 : [5896] 00000000 : 7B 22 43 6F 6E 6E 65 63-74 69 6F 6E 73 22 3A 7B : {"Connections":{
DateTime=2019-06-24T06:43:09.1091858Z
...
System.Net.Sockets Verbose: 0 : [5896] Socket#11429296::BeginSend()
DateTime=2019-06-24T06:43:09.1140970Z
System.Net.Sockets Verbose: 0 : [5896] Exiting Socket#11429296::BeginSend()     -> OverlappedAsyncResult#60375305
DateTime=2019-06-24T06:43:09.1151910Z
System.Net Verbose: 0 : [5896] Exiting ConnectStream#17987329::BeginWrite()     -> NestedSingleAsyncResult#46228029
DateTime=2019-06-24T06:43:09.1160992Z
System.Net.Sockets Verbose: 0 : [6420] Data from Socket#11429296::PostCompletion
DateTime=2019-06-24T06:43:09.1180991Z
System.Net.Sockets Verbose: 0 : [6420] 00000000 : 7B 22 43 6F 6E 6E 65 63-74 69 6F 6E 73 22 3A 7B : {"Connections":{
DateTime=2019-06-24T06:43:09.1180991Z
...
System.Net.Sockets Verbose: 0 : [6420] Socket#11429296::EndSend(OverlappedAsyncResult#60375305)
DateTime=2019-06-24T06:43:09.1212220Z
System.Net.Sockets Verbose: 0 : [6420] Exiting Socket#11429296::EndSend()   -> Int32#125
DateTime=2019-06-24T06:43:09.1212220Z
System.Net Verbose: 0 : [6420] ConnectStream#17987329::EndWrite()
DateTime=2019-06-24T06:43:09.1212220Z
System.Net Verbose: 0 : [6420] Exiting ConnectStream#17987329::EndWrite() 
DateTime=2019-06-24T06:43:09.1222229Z
System.Net Verbose: 0 : [6420] ConnectStream#17987329::Close()
DateTime=2019-06-24T06:43:09.1222229Z
System.Net Verbose: 0 : [6420] Exiting ConnectStream#17987329::Close() 
DateTime=2019-06-24T06:43:09.1232215Z
System.Net Verbose: 0 : [7368] HttpWebRequest#52253787::BeginGetResponse()
DateTime=2019-06-24T06:43:09.1232215Z
System.Net Verbose: 0 : [7368] Exiting HttpWebRequest#52253787::BeginGetResponse()  -> ContextAwareResult#13009416
DateTime=2019-06-24T06:43:09.1241884Z
System.Net Verbose: 0 : [7368] HttpWebRequest#52253787::Abort()
DateTime=2019-06-24T06:43:18.7330583Z

Wireshark:

Protocol Length Info
TCP      66     56916 → 33444 [SYN] Seq=0 Win=8192 Len=0 MSS=1432 WS=256 SACK_PERM=1
TCP      66     33444 → 56916 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1404 WS=256 SACK_PERM=1
TCP      54     56916 → 33444 [ACK] Seq=1 Ack=1 Win=65792 Len=0
HTTP     248    POST /Service_v2/GetServerInformation/ HTTP/1.1 
TCP      60     33444 → 56916 [ACK] Seq=1 Ack=195 Win=65792 Len=0
HTTP     438    HTTP/1.1 200 OK  (text/plain)
TCP      54     56916 → 33444 [ACK] Seq=195 Ack=385 Win=65536 Len=0
HTTP     220    POST /Service_v2/GetServerLicense/ HTTP/1.1 
TCP      60     33444 → 56916 [ACK] Seq=385 Ack=361 Win=65792 Len=0
HTTP     1252   HTTP/1.1 200 OK  (text/plain)
TCP      54     56916 → 33444 [ACK] Seq=361 Ack=1583 Win=65792 Len=0
HTTP     220    POST /Service_v2/GetSecondMessage/ HTTP/1.1 
TCP      60     33444 → 56916 [ACK] Seq=1583 Ack=527 Win=65536 Len=0
HTTP     858    HTTP/1.1 200 OK  (text/plain)
HTTP     265    POST /Service_v2/GetMainMessage/?messageid=10d5d406-634e-4b65-9d99-f614e8b8398b HTTP/1.1 
TCP      60     33444 → 56916 [ACK] Seq=2387 Ack=738 Win=65280 Len=0
HTTP     836    HTTP/1.1 200 OK  (text/plain)
TCP      241    56916 → 33444 [PSH, ACK] Seq=738 Ack=3169 Win=65792 Len=187 [TCP segment of a reassembled PDU]
TCP      60     33444 → 56916 [ACK] Seq=3169 Ack=925 Win=65024 Len=0
HTTP     79     HTTP/1.1 100 Continue 
HTTP     181    POST /Service_v2/ProcessMessage/ HTTP/1.1  (application/raw)
TCP      60     33444 → 56916 [ACK] Seq=3194 Ack=1052 Win=65024 Len=0
HTTP     372    HTTP/1.1 200 OK  (text/plain)
TCP      54     56916 → 33444 [ACK] Seq=1052 Ack=3512 Win=65536 Len=0
HTTP     220    POST /Service_v2/GetSecondMessage/ HTTP/1.1 
TCP      60     33444 → 56916 [ACK] Seq=3512 Ack=1218 Win=64768 Len=0
HTTP     882    HTTP/1.1 200 OK  (text/plain)
TCP      54     56916 → 33444 [ACK] Seq=1218 Ack=4340 Win=64768 Len=0
    Here I try to make new POST /Service_v2/ProcessMessage/ HTTP/1.1  (application/raw) but there are NO data in WireShark
I see only next line ([RST, ACK]) after 2 minutes, no [FIN], no [ASK], no [PSH]
TCP      60     33444 → 56916 [RST, ACK] Seq=4340 Ack=1218 Win=0 Len=0

源代码:

public ServerHttpRequest(string methodSuffix, NameValueCollection requestParams = null, string requestBody = null)
{
    if (methodSuffix == null)
        throw new AggregateException(nameof(methodSuffix));

    _methodSuffix = methodSuffix;
    _requestParams = requestParams;
    _requestBody = requestBody;
}

public async Task<string> SendRequest()
{
    var sendRequestTask = Send();

    if (await Task.WhenAny(sendRequestTask, Task.Delay(TimeSpan.FromSeconds(Configuration.ServerTimeout))) == sendRequestTask)
        return await sendRequestTask.ConfigureAwait(false);

    ThreadPool.QueueUserWorkItem(this.Abort);
    throw new TimeoutException("HttpRequest timeout exceeded. Probably having problems connecting to the server.");
}

private void Abort(object obj)
{
    try
    {
        _httpRequest?.Abort();
    }
    catch (Exception ex)
    {
        Log(ex);
    }
}

private HttpWebRequest CreateRequest(string methodSuffix, NameValueCollection requestParams = null)
{
    string url = GetUrl(methodSuffix) 

    if (requestParams != null && requestParams.Count > 0)
            serviceAdress = AddParamsToUrl(url, requestParams);

    var webRequest = WebRequest.CreateHttp(licServiceAdress);

    webRequest.Method = "POST";

    //The Timeout property indicates the length of time, in milliseconds,
    //until the request times out and throws a WebException.
    //The Timeout property affects only synchronous requests made with the GetResponse method.
    //https://docs.microsoft.com/en-us/dotnet/api/system.net.webrequest.timeout?view=netframework-4.8#remarks
    webRequest.Timeout = (int)TimeSpan.FromSeconds(Configuration.ServerTimeout).TotalMilliseconds;

    webRequest.Proxy = null;
    webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

    webRequest.Headers.Add("Accept-Encoding", "gzip");

    return webRequest;
}

private async Task<string> Send()
{
    try
    {
        _httpRequest = await Task.Run(() => CreateRequest(_methodSuffix, _requestParams)).ConfigureAwait(false);

        UTF8Encoding encoding = new UTF8Encoding();
        byte[] requestBodyBytes = null;
        if (_requestBody == null)
            requestBodyBytes = encoding.GetBytes("");
        else
            requestBodyBytes = encoding.GetBytes(_requestBody);

        _httpRequest.ContentType = "application/raw";
        _httpRequest.ContentLength = requestBodyBytes.Length;

        using (Stream newStream = await _httpRequest.GetRequestStreamAsync().ConfigureAwait(false))
        {
            await newStream.WriteAsync(requestBodyBytes, 0, requestBodyBytes.Length).ConfigureAwait(false);
        }

        using (var webResponse = (HttpWebResponse)await _httpRequest.GetResponseAsync().ConfigureAwait(false))
        {
            using (var responseStream = webResponse.GetResponseStream())
                if (responseStream != null)
                    using (var reader = new StreamReader(responseStream))
                        return await reader.ReadToEndAsync().ConfigureAwait(false);


            return "";
        }

    }
    catch (Exception ex)
    {
        Log($"Request failed. Uri: '{_httpRequest.RequestUri.AbsoluteUri}'. {ex}");

        throw;
    }
}

我需要知道为什么套接字数据没有显示在Wireshark中。如何诊断呢?

0 个答案:

没有答案