简体   繁体   English

SignalR客户端连接错误(UWP和JavaScript客户端)

[英]SignalR client connection error (UWP & JavaScript Client)

I have both, a simple UWP app running on local machine in Visual Studio and a simple AngularJS SPA. 我既有一个在Visual Studio中本地计算机上运行的简单UWP应用程序,又有一个简单的AngularJS SPA。 I have also an OWIN based self hosted server running in a Service Fabric Cluster. 我还有一个在Service Fabric群集中运行的基于OWIN的自托管服务器。 The server use web api and signalR. 服务器使用Web api和signalR。

When I'm hosting the Service Fabric Cluster on my local machine, the UWP app and the angular app can open a connection to a signalR hub on the server. 当我在本地计算机上托管Service Fabric群集时,UWP应用程序和angular应用程序可以打开与服务器上SignalR集线器的连接。 When I'm hosting the Service Fabric Cluster on Azure, the clients are not able to connect to the signalR hub. 当我在Azure上托管Service Fabric群集时,客户端无法连接到signalR集线器。 I'm getting: failed: Error during WebSocket handshake: Unexpected response code: 400 我得到: failed: Error during WebSocket handshake: Unexpected response code: 400

Server side code in startup class: 启动类中的服务器端代码:

        public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration httpConfig = this.ConfigureWebApi();
            FileServerOptions fileServerOptions = this.ConfigureFileSystem(appBuilder);                           appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            appBuilder.UseWebApi(this.ConfigureWebApi());
            appBuilder.UseFileServer(fileServerOptions);
            appBuilder.MapSignalR();

SignalR hub class on server: 服务器上的SignalR集线器类:

    public class SensorDataHub : Hub
    {
        public void UpdateSensorData(SensorDataModel data)
        {
            Clients.All.updateChartData(data);
        }            
    }

UWP code: UWP代码:

        private async void OpenSignalRConnection()
        {    
            //this.SensorDataHubCon = new HubConnection("http://localhost:80/");
            this.SensorDataHubCon = new HubConnection("http://rivutec.westeurope.cloudapp.azure.com/");
            this.SensorDataHubProxy = this.SensorDataHubCon.CreateHubProxy("SensorDataHub");

            await this.SensorDataHubCon.Start();
        }

AngularJS code: AngularJS代码:

            var connection = $.hubConnection("http://localhost:80/");
            //var connection = $.hubConnection("http://test.server.com/");
            var proxy = connection.createHubProxy("SensorDataHub");

            proxy.on("updateChartData", function (data) {
                console.log(data.current);
            });

            connection.start()
                .done(function () { console.log('Now connected, connection ID=' + $.connection.hub.id); })
                .fail(function () { console.log('Could not Connect!'); });

As I wrote above, the UWP client and the angular client can open the hub connection to localhost . 正如我在上面写的,UWP客户端和angular客户端可以打开到localhost的集线器连接。

But when I'm trying to connect the UWP client to a signalR hub published on a cloud, I'm getting a Bad Request error: 但是,当我尝试将UWP客户端连接到发布在云上的signalR集线器时,出现了Bad Request错误:

Microsoft.AspNet.SignalR.Client.HttpClientException was unhandled by user code
  HResult=-2146233088
  Message=StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Server: Microsoft-HTTPAPI/2.0
  Transfer-Encoding: chunked
  Date: Sun, 07 Feb 2016 13:59:09 GMT
  X-Content-Type-Options: nosniff
}
  Source=Microsoft.AspNet.SignalR.Client
  StackTrace:
       at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.<>c__DisplayClass6.<Post>b__5(HttpResponseMessage responseMessage)
       at Microsoft.AspNet.SignalR.TaskAsyncHelper.<>c__DisplayClass19`2.<Then>b__17(Task`1 t)
       at Microsoft.AspNet.SignalR.TaskAsyncHelper.TaskRunners`2.<>c__DisplayClass42.<RunTask>b__41(Task`1 t)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at SerialSample.MainPage.<OpenSignalRConnection>d__9.MoveNext()
  InnerException: 

And the signalR trace says: 而signalR跟踪显示:

13:59:02.3510728 - ac120389-8e08-4690-8e38-4538b602260e - SSE: GET http://test.server.com/signalr/connect?clientProtocol=1.4&transport=serverSentEvents&connectionData=[{"Name":"SensorDataHub"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVQGqCkfcnkONWeEawJYNqQAAAAACAAAAAAAQZgAAAAEAACAAAADhW4uMBq5ClXKT3X5UGNGLq3YzdxgD4blCiGSRFL8b8AAAAAAOgAAAAAIAACAAAABGZnghjduUUMHt3QMlhMxIRsajzvG0kWW4ECTpnppl4DAAAAALVIQ46T3%2BdnUpON%2FrpgZO8idns8YNkRrK9lMMxKQz7xYTgM8ViIcxeMNx7%2FamQsRAAAAA5KtFAgG0yKxNVlzAfGNc0cHP8NXxEmaK1i%2Blf52xb7SNmpz%2B5O%2BJxZmVz71Z3pdHV4Z1LyGJixJsRxnQEJOtfA%3D%3D&noCache=28c5a100-2796-4287-958b-0c2ccbd1e91a
The thread 0x4b04 has exited with code 0 (0x0).
13:59:07.3914634 - ac120389-8e08-4690-8e38-4538b602260e - Auto: Failed to connect to using transport serverSentEvents. System.TimeoutException: Transport timed out trying to connect
13:59:07.3994644 - ac120389-8e08-4690-8e38-4538b602260e - LP Connect: http://test.server.com/signalr/connect?clientProtocol=1.4&transport=longPolling&connectionData=[{"Name":"SensorDataHub"}]&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVQGqCkfcnkONWeEawJYNqQAAAAACAAAAAAAQZgAAAAEAACAAAADhW4uMBq5ClXKT3X5UGNGLq3YzdxgD4blCiGSRFL8b8AAAAAAOgAAAAAIAACAAAABGZnghjduUUMHt3QMlhMxIRsajzvG0kWW4ECTpnppl4DAAAAALVIQ46T3%2BdnUpON%2FrpgZO8idns8YNkRrK9lMMxKQz7xYTgM8ViIcxeMNx7%2FamQsRAAAAA5KtFAgG0yKxNVlzAfGNc0cHP8NXxEmaK1i%2Blf52xb7SNmpz%2B5O%2BJxZmVz71Z3pdHV4Z1LyGJixJsRxnQEJOtfA%3D%3D&noCache=78a5c718-439d-440f-9b68-c0658135209f
'SerialSample.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\...\Downloads\samples-develop\samples-develop\SerialSample\CS\bin\x86\Debug\AppX\System.Net.Requests.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
13:59:07.5434999 - ac120389-8e08-4690-8e38-4538b602260e - Auto: Failed to connect to using transport longPolling. Microsoft.AspNet.SignalR.Client.HttpClientException: StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Server: Microsoft-HTTPAPI/2.0
  Transfer-Encoding: chunked
  Date: Sun, 07 Feb 2016 13:59:09 GMT
  X-Content-Type-Options: nosniff
}
   at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.<>c__DisplayClass6.<Post>b__5(HttpResponseMessage responseMessage)
   at Microsoft.AspNet.SignalR.TaskAsyncHelper.<>c__DisplayClass19`2.<Then>b__17(Task`1 t)
   at Microsoft.AspNet.SignalR.TaskAsyncHelper.TaskRunners`2.<>c__DisplayClass42.<RunTask>b__41(Task`1 t)
13:59:07.5755002 - ac120389-8e08-4690-8e38-4538b602260e - OnError(Microsoft.AspNet.SignalR.Client.HttpClientException: StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Server: Microsoft-HTTPAPI/2.0
  Transfer-Encoding: chunked
  Date: Sun, 07 Feb 2016 13:59:09 GMT
  X-Content-Type-Options: nosniff
}
   at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.<>c__DisplayClass6.<Post>b__5(HttpResponseMessage responseMessage)
   at Microsoft.AspNet.SignalR.TaskAsyncHelper.<>c__DisplayClass19`2.<Then>b__17(Task`1 t)
   at Microsoft.AspNet.SignalR.TaskAsyncHelper.TaskRunners`2.<>c__DisplayClass42.<RunTask>b__41(Task`1 t))
13:59:07.6070094 - ac120389-8e08-4690-8e38-4538b602260e - Disconnected
13:59:07.6100082 - ac120389-8e08-4690-8e38-4538b602260e - Transport.Dispose(ac120389-8e08-4690-8e38-4538b602260e)
13:59:07.6135102 - ac120389-8e08-4690-8e38-4538b602260e - Closed
Exception thrown: 'Microsoft.AspNet.SignalR.Client.HttpClientException' in mscorlib.ni.dll

And the angular client error says: 和有角度的客户端错误说:

[21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Client subscribed to hub 'sensordatahub'.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Negotiating with 'http://test.server.com//signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D'.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: webSockets transport starting.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Connecting to websocket endpoint 'ws://test.server.com/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVQGqCkfcnkONWeEawJYNqQAAAAACAAAAAAAQZgAAAAEAACAAAAC8DLAeriEnbunGPma3%2F%2FChRl1tm6XCfCHDLEEBfpjszgAAAAAOgAAAAAIAACAAAACANAtQqijBRvg4FloVq0JnylH9%2Bm6j5coY3Yr0yP60mzAAAAD4qw2VdYIQJ3CYQPcPbr2LhyfPhhJtPPgJ33FZuPLQh8owubvHYD5jhRsXdMxHfitAAAAAJX0cLVthvatbmOa%2BNbRSt%2B8CnVJ%2FQ9ks1x%2Bzlk2wA8iF6OVU03wXaNK17FXK2%2BlFmU6hIk8euqJVXeZMz7%2Bfnw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D&tid=4'.
jquery.signalR.min.js:8 WebSocket connection to 'ws://test.server.com/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=AQAAANCMnd8BFdERjHoAwE%2FCl%2BsBAAAAVQGqCkfcnkONWeEawJYNqQAAAAACAAAAAAAQZgAAAAEAACAAAAC8DLAeriEnbunGPma3%2F%2FChRl1tm6XCfCHDLEEBfpjszgAAAAAOgAAAAAIAACAAAACANAtQqijBRvg4FloVq0JnylH9%2Bm6j5coY3Yr0yP60mzAAAAD4qw2VdYIQJ3CYQPcPbr2LhyfPhhJtPPgJ33FZuPLQh8owubvHYD5jhRsXdMxHfitAAAAAJX0cLVthvatbmOa%2BNbRSt%2B8CnVJ%2FQ9ks1x%2Bzlk2wA8iF6OVU03wXaNK17FXK2%2BlFmU6hIk8euqJVXeZMz7%2Bfnw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D&tid=4' failed: Error during WebSocket handshake: Unexpected response code: 400
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Websocket closed.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Closing the Websocket.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: webSockets transport failed to connect. Attempting to fall back.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: serverSentEvents transport starting.
jquery.signalR.min.js:8 [21:52:32 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Attempting to connect to SSE endpoint 'http://test.server.com/signalr/connect?transport=serv…nw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D&tid=6'.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: serverSentEvents transport timed out when trying to connect.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: EventSource calling close().
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: serverSentEvents transport failed to connect. Attempting to fall back.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: foreverFrame transport starting.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Forever Frame is not supported by SignalR on browsers with SSE support.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: foreverFrame transport failed to connect. Attempting to fall back.
jquery.signalR.min.js:8 [21:52:37 GMT+0100 (Mitteleuropäische Zeit)] SignalR: longPolling transport starting.
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Opening long polling request to 'http://test.server.com/signalr/connect?transport=long…z7%2Bfnw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D'.
jquery.min.js:4 POST http://test.server.com/signalr/connect?transport=long…z7%2Bfnw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D 400 (Bad Request)l.cors.b.crossDomain.send @ jquery.min.js:4n.extend.ajax @ jquery.min.js:4r.transports._logic.ajax @ jquery.signalR.min.js:8e @ jquery.signalR.min.js:8(anonymous function) @ jquery.signalR.min.js:8
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: longPolling transport failed to connect. Attempting to fall back.
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Fallback transports exhausted.
signalRHubService.js:13 Could not Connect!
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Stopping connection.
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: Fired ajax abort async = true.
jquery.signalR.min.js:8 [21:52:38 GMT+0100 (Mitteleuropäische Zeit)] SignalR: LongPolling failed to connect.
jquery.min.js:4 POST http://test.server.com//signalr/abort?transport=longP…z7%2Bfnw%3D%3D&connectionData=%5B%7B%22name%22%3A%22sensordatahub%22%7D%5D 400 (Bad Request)l.cors.b.crossDomain.send @ jquery.min.js:4n.extend.ajax @ jquery.min.js:4r.transports._logic.ajax @ jquery.signalR.min.js:8r.transports._logic.ajaxAbort @ jquery.signalR.min.js:8r.transports.longPolling.abort @ jquery.signalR.min.js:8r.fn.r.stop @ jquery.signalR.min.js:8a.state.r.connectionState.connecting.d @ jquery.signalR.min.js:8v @ jquery.signalR.min.js:8h.transportFailed @ jquery.signalR.min.js:8(anonymous function) @ jquery.signalR.min.js:8y @ jquery.signalR.min.js:8s.pollXhr.i.ajax.error @ jquery.signalR.min.js:8i @ jquery.min.js:2j.fireWith @ jquery.min.js:2z @ jquery.min.js:4(anonymous function) @ jquery.min.js:4

I'm getting failed: Error during WebSocket handshake: Unexpected response code: 400 . failed: Error during WebSocket handshake: Unexpected response code: 400 Why can I connect on localhost, but not on cloud? 为什么我可以在本地主机上连接,但不能在云上连接?

Without seeing more of your code, this is just a WAG, but... 没有看到更多代码,这只是一个WAG,但是...

Based on the fact that it was a 'Bad Request' error and the log says it timed out on all the transport types, my instincts are telling me that on your local machine, 基于这是一个“错误请求”错误并且日志显示所有传输类型都超时的事实,我的直觉告诉我在您的本地计算机上,

  • when you configure the uri for the OWIN self host, you tell it to bind to localhost:80. 为OWIN自主机配置uri时,告诉它绑定到localhost:80。
  • When the service fabric local cluster starts and runs the Stateful/lessService (or I suppose you could do it with Actors) it instantiates the OWIN self-host 当服务结构本地集群启动并运行Stateful / lessService时(或者我想您可以使用Actors进行操作),它将实例化OWIN自托管
  • OWIN binds to localhost:80 and requests to localhost:80 are correctly routed there OWIN绑定到localhost:80并将对localhost:80的请求正确路由到那里
  • Warm fuzzies are had. 有温暖的模糊感。

    However, when moving the cluster up to Azure: 但是,将群集升级到Azure时:

  • you want to change the OWIN uri address, because localhost is no longer appropriate, 您想更改OWIN uri地址,因为localhost已不再适用,

  • so you chose 'test.server.com', or whatever it actually was. 因此您选择了“ test.server.com”,或实际上是什么。
  • Now though, the cluster isn't on a single machine, it's up in Azure and whatever binding you want to use probably isn't valid. 但是,现在群集不在单个计算机上,而是在Azure中运行,而您要使用的任何绑定都可能无效。
  • Meaning, your OWIN host may be listening for 'test.server.com' requests, but none are coming because no DNS is pointing 'test.server.com' to the service fabric machine(s) hosting the service (which is hosting the OWIN self-host). 这意味着,您的OWIN主机可能正在侦听“ test.server.com”请求,但是没有人来,因为没有DNS会将“ test.server.com”指向托管该服务的服务结构计算机(托管该服务结构计算机)。 OWIN自托管)。

    Some documentation I read noted that the service fabric framework has its own name servers which resolve the service fabric references to actual machine address, which is why you refer to service fabric services using the 'fabric:' protocol and let the routing magic happen behind the scenes. 我读过的一些文档指出,服务结构框架有自己的名称服务器,这些服务器将服务结构的引用解析为实际的机器地址,这就是为什么您使用“ fabric:”协议引用服务结构服务并使路由魔术发生在服务器背后的原因。场景。 So the same limitation that means you can't directly expose an HTTP endpoint for a Service Fabric service without using an intermediary (see this MSDN article for details), is going to limit your ability to self host and bind to a uri that external clients can use. 因此,同样的限制意味着您不能不使用中介就无法直接公开Service Fabric服务的HTTP终结点(有关详细信息,请参阅此MSDN文章 ),这将限制您自托管和绑定外部客户端uri的能力。可以使用。

This article talks about using OWIN to self-host Web API in an Azure Worker role, but the example is limited to using the local emulator and doesn't seem to address the fact that the ip address assigned to the endpoint could and would change in the cloud, making it hard to address reliably on the client. 本文讨论了使用OWIN在Azure Worker角色中自托管Web API,但是该示例仅限于使用本地仿真器,似乎并未解决分配给端点的IP地址可能会更改的事实。云,很难在客户端上可靠地进行寻址。

If you were trying to move the SignalR hub to Service Fabric because you wanted to be able to take advantage of Service Fabric's scalability, check here . 如果您想将SignalR集线器移至Service Fabric,是因为您希望能够利用Service Fabric的可扩展性, 请查看此处 The currently recommended/supported path to scale out SignalR that looks like the best fit for what you've got there would be using Web Roles and Azure Service Bus as shown here . 如上所示,使用Web Roles和Azure Service Bus来扩展当前看起来最适合SignalR的SignalR的当前推荐/支持路径。

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

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