SignalR Asp.netcore 和 angular(WebSocket 未处于 OPEN 状态)断开信号R.HttpTransportType.WebSockets

Posted

技术标签:

【中文标题】SignalR Asp.netcore 和 angular(WebSocket 未处于 OPEN 状态)断开信号R.HttpTransportType.WebSockets【英文标题】:SignalR Asp.netcore and angular ( WebSocket is not in the OPEN state) disconnection for signalR.HttpTransportType.WebSockets 【发布时间】:2020-04-19 23:11:09 【问题描述】:

将 .NET Core 2.2 和 Angular 8 与包 "@aspnet/signalr": "^1.1.4" 一起使用。 我在 .NET Core 2.2 中设置了一个集线器,它可以与另一个使用相同包的 Angular 项目正常工作。

Startup.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using SignalrChat.Services;

namespace SignalrChat

    public class Startup
    
        public Startup(IConfiguration configuration)
        
            Configuration = configuration;
        

        public IConfiguration Configuration  get; 

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        
            services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
            
                builder
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed(_ => true)
                .AllowCredentials();
            ));
            services.AddSignalR();
            services.AddSingleton<IChatRoomService, InMemoryChatRoomService>();
            services.AddControllers();
        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            

            app.UseRouting();

            app.UseAuthorization();

            app.UseCors("CorsPolicy");
            app.UseEndpoints(endpoints =>
            
                endpoints.MapControllers();
                endpoints.MapHub<ChatHub>("/chat");
            );
        
    

枢纽:

using Microsoft.AspNetCore.SignalR;
using SignalrChat.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SignalrChat

    public class ChatHub : Hub
    

角度:

import * as signalR from "@aspnet/signalr";
import 
  Component, Inject, OnInit
 from '@angular/core';

import  DeviceDetectorService  from 'ngx-device-detector';
import  DOCUMENT  from '@angular/common';
import  Router  from '@angular/router';

@Component(
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
)
export class AppComponent implements OnInit 
    ngOnInit(): void 
        this.hub = new signalR.HubConnectionBuilder()
            .configureLogging(signalR.LogLevel. Trace)
        .withUrl('http://localhost:56328/chat')
        
            .build();

        this.hub.serverTimeoutInMilliseconds = 100000;
        this.hub.keepAliveIntervalInMilliseconds = 100000;
        this.hub
            .start()
            .then(() =>   
                console.log('Connection started!');
                console.log('Getting all rooms');  

            )
            .catch(err => 
                console.log(err);
                console.log(this.hub);
                
            );
    

这是来自 Angular 项目的 hub.start() 的日志,运行良好:

[2019-12-31T11:43:30.214Z] Debug: Starting HubConnection.
Utils.js:213 [2019-12-31T11:43:30.215Z] Debug: Starting connection with transfer format 'Text'.
Utils.js:213 [2019-12-31T11:43:30.220Z] Debug: Sending negotiation request: http://localhost:56328/chat/negotiate.
Utils.js:213 [2019-12-31T11:43:31.382Z] Debug: Selecting transport 'WebSockets'.
client:52 [WDS] Live Reloading enabled.
Utils.js:209 [2019-12-31T11:43:32.001Z] Information: WebSocket connected to ws://localhost:56328/chat?id=NafCuVY_brPNmqQlN2EvXw.
Utils.js:213 [2019-12-31T11:43:32.003Z] Debug: Sending handshake request.
Utils.js:209 [2019-12-31T11:43:32.006Z] Information: Using HubProtocol 'json'.
Utils.js:213 [2019-12-31T11:43:32.053Z] Debug: Server handshake complete.

但是对于具有完全相同的代码和打包到同一个集线器的另一个 Angular 项目,它无法继续。这是日志:

[2019-12-31T11:41:35.294Z] Debug: Starting HubConnection.
Utils.js:213 [2019-12-31T11:41:35.639Z] Debug: Starting connection with transfer format 'Text'.
Utils.js:213 [2019-12-31T11:41:35.644Z] Debug: Sending negotiation request: http://localhost:56328/chat/negotiate.
core.js:16829 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
Utils.js:213 [2019-12-31T11:41:36.574Z] Debug: Selecting transport 'WebSockets'.
WebSocket connection to 'ws://localhost:4200/sockjs-node/694/1skccdzm/websocket' failed: WebSocket is closed before the connection is established.
[2019-12-31T11:41:38.814Z] Information: WebSocket connected to ws://localhost:56328/chat?id=qO3s36husX9-boU1SwyaBg.
Utils.js:213 [2019-12-31T11:41:38.820Z] Debug: Sending handshake request.
app.component.ts:34 WebSocket is not in the OPEN state

我尝试将“not-wroking angular”的所有包更改为与“working-angular”相同的包,问题仍然存在。

更新

我发现更改 signalR.HubConnectionBuilder() 的 http 传输模式将使其工作如下:

var options = 
    transport: signalR.HttpTransportType.ServerSentEvents ,
    logging: signalR.LogLevel.Trace, 
;
this.hub = new signalR.HubConnectionBuilder()
    //.withUrl('http://localhost:56328/chat' , options)
    .withUrl('http://localhost:49941/chat', options) 
    .build();

ServerSentEvent 成功,websocket 和 longpolling 模式不成功。

【问题讨论】:

如果您从同一个客户端浏览这两个 Angular 应用程序,是否也可以使用 websocketlongpolling 传输? 请检查the issue is caused by zone.js. @Fei Han:谢谢你的回复,是的,我的电脑上有两个 Angular 应用程序,一个适用于 websocket,另一个适用于 serverSentEvent。 @韩飞:同一台电脑* 【参考方案1】:

感谢@Fei Han 提到这个有用的solution: 当我将代码更改为此时,它起作用了:

 Object.defineProperty(WebSocket, 'OPEN',  value: 1, ); 
        this.hub
            .start()
            .then(() =>                      
                console.log('Connection started!');         

            )
            .catch(err => 
                console.log(err);                     
            );

【讨论】:

以上是关于SignalR Asp.netcore 和 angular(WebSocket 未处于 OPEN 状态)断开信号R.HttpTransportType.WebSockets的主要内容,如果未能解决你的问题,请参考以下文章

SignalR学习

带有 SignalR 集线器的 ASP.NET Core 中的范围服务

使用 SignalR (ASP.NET Core) 的多个单聊天室

ASP.NET Core的实时库: SignalR -- 预备知识

Angular 和 .NET Core 的 SignalR CORS 问题

从 Controller 调用 SignalR Core Hub 方法