HttpClient.SendAsync与Socket.IO挂起通话

时间:2019-01-07 15:30:38

标签: c# asp.net sockets socket.io .net-core

HttpClient.SendAsync在ASP.NET Core 2.0中运行时挂在对Socket.IO的协议升级GET请求调用上,但相同的代码在.NET 4.7上成功运行

我构建了一个包含所有Socket.IO握手逻辑的类(我使用Chrome开发人员工具和Wireshark进行了反向工程)。在使用.NET 4.7和GTK#构建的测试GUI应用程序中运行时,此类成功完成了一次握手(并且可以成功发送emit()条消息),但是在ASP.NET Core中运行时,该类挂起了protocol upgrade GET请求2。

请注意,握手的前两个步骤起作用,它们还使用HttpClient(获取会话ID,选择room(命名空间)。第三次调用失败,仅在ASP.NET中Core 2 (请参见下面的代码)。最后,我在.NET 4.7应用程序和ASP.NET Core 2中在所有调用中都使用了 same HttpClient实例(我建立了一个名为SocketMediator的类,并且在两个地方都使用了该类。

我用于协议升级请求的URL是"http://127.0.0.1:7200/socket.io/?EIO=3&transport=polling&t=1546875159&sid=cD5KhP_8FKPV-ojhAAAA" sid,它是在第一个调用中提供的,并且t是生成的时间戳。

using (var protocolUpgradeRequest = new HttpRequestMessage(HttpMethod.Get, probeTURl))
        {
            protocolUpgradeRequest.Headers.Add("DNT", "1");
            protocolUpgradeRequest.Headers.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3642.0 Safari/537.36");
            protocolUpgradeRequest.Headers.Add("Cookie", $"io={sessionId}");
            protocolUpgradeRequest.Headers.Add("Connection", "Upgrade");
            protocolUpgradeRequest.Headers.Add("Pragma", "no-cache");
            protocolUpgradeRequest.Headers.Add("Cache-control", "no-cache");
            protocolUpgradeRequest.Headers.Add("Upgrade", "websocket");
            protocolUpgradeRequest.Headers.Add("Sec-Websocket-Version", "13");
            protocolUpgradeRequest.Headers.Add("Accept-Encoding", "gzip, deflate, br");
            protocolUpgradeRequest.Headers.Add("Sec-Websocket-Key", websocketKey);
            protocolUpgradeRequest.Headers.Add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits");

            try
            {
                using (var response = await httpClient.SendAsync(protocolUpgradeRequest, CancellationToken.None))
                {
                    if (response.StatusCode != HttpStatusCode.SwitchingProtocols)
                    {
                        throw new HttpRequestException(
                            "Did not correctly receive protocol switch from server!");
                    }

                    var accept = response.Headers.GetValues("Sec-Websocket-Accept");

                    if (!accept.Any())
                    {
                        throw new HttpRequestException("Did not get Sec-Websocket-Accept header!");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex);
                throw ex;
            }
        }

我逐步完成了Socket.IO中的握手JS代码,可以看到它接受了协议升级。它返回一个成功的确认(返回Sec-Websocket-Accept头),但是HttpClient.SendAsync坐在那里挂了(我也看到Wireshark也返回了这个头。Socket.IO最终关闭了套接字,因为这种挂起会导致{ {1}}。当插座强制关闭时,ping timeout会“松开”并继续。

同样,此问题的关键是在.NET 4.7中运行时,它工作正常(即使我构建的类位于dotnet标准2.0项目中!)

我已验证自己“一直向下同步”。我实际上有一个SendAsync()在ASP.NET Core 2中运行,可以异步启动此连接。

0 个答案:

没有答案