SignalR Asp.netcore 和 angular(WebSocket 未处于 OPEN 状态)断开 signalR.HttpTransportType.WebSockets
SignalR Asp.netcore and angular ( WebSocket is not in the OPEN state) disconnection for signalR.HttpTransportType.WebSockets
使用 .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
{}
}
Angular:
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模式不成功
感谢@Fei Han 提到这个有用solution:
当我把我的代码改成这个时它起作用了:
Object.defineProperty(WebSocket, 'OPEN', { value: 1, });
this.hub
.start()
.then(() => {
console.log('Connection started!');
})
.catch(err => {
console.log(err);
});
使用 .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
{}
}
Angular:
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模式不成功
感谢@Fei Han 提到这个有用solution: 当我把我的代码改成这个时它起作用了:
Object.defineProperty(WebSocket, 'OPEN', { value: 1, });
this.hub
.start()
.then(() => {
console.log('Connection started!');
})
.catch(err => {
console.log(err);
});