SignalR 无法使用任何可用的传输方式从客户端连接到服务器

问题描述 投票:0回答:2

我正在尝试连接到我的服务器 (.NET) 上使用 SignalR 建立的 websocket。

我的客户端(JavaScript)开始协商,获得带有connectionId、connectionToken等的响应,但随后无法与任何可用的传输方法连接。

我得到的最后一个调试跟踪是这样的:

[2022-11-17T10:21:02.093Z] Debug: HubConnection failed to start successfully because of error 'Error: Unable to connect to the server with any of the available transports. WebSockets failed: Error: There was an error with the transport. ServerSentEvents failed: Error: Error occurred LongPolling failed: Error'.

我的服务器代码:

启动.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace Sample
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddNewtonsoftJson();
            services.AddSignalR().AddNewtonsoftJsonProtocol(opt => {
                opt.PayloadSerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            });
            services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.WithOrigins("http://localhost:8080", "http://127.0.0.1:8080")
                       .AllowAnyMethod()
                       .AllowAnyHeader()
                       .AllowCredentials();
            }));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseFileServer();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseCors("MyPolicy");
            app.UseMvc();
            app.UseRouting();
            app.UseEndpoints(routes =>
            {
                routes.MapHub<Controllers.DesignAutomationHub>("/api/signalr/designautomation");
            });

        }
    }
}

控制器:

using Autodesk.Forge;
using Autodesk.Forge.DesignAutomation;
using Autodesk.Forge.DesignAutomation.Model;
using Autodesk.Forge.Model;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.Controllers
{
    [ApiController]
    public class ServiceController : Controller
    {
        // Design Automation v3 API
        DesignAutomationClient _designAutomation;
        // Used to access the application folder (temp location for files & bundles)
        private IWebHostEnvironment _env;
        // used to access the SignalR Hub
        private IHubContext<DesignAutomationHub> _hubContext;

        public ServiceController(IWebHostEnvironment env, IHubContext<DesignAutomationHub> hubContext, DesignAutomationClient api)
        {
            _designAutomation = api;
            _env = env;
            _hubContext = hubContext;
        }
    }

    /// <summary>
    /// Class uses for SignalR
    /// </summary>
    public class DesignAutomationHub : Microsoft.AspNetCore.SignalR.Hub
    {
        public string GetConnectionId() { return Context.ConnectionId; }
    }
}

客户:

var connection;
var connectionId;

function startConnection(onReady) {
  if (connection && connection.connectionState) {
    if (onReady) onReady();
    return;
  }
  connection = new signalR.HubConnectionBuilder()
    .withUrl(
      "http://<SERVERADRESS>/api/signalr/designautomation"
    )
    .configureLogging(signalR.LogLevel.Trace)
    .build();
  connection.start().then(function () {
    connection.invoke("getConnectionId").then(function (id) {
      connectionId = id; 
      if (onReady) onReady();
    });
  });

  connection.on("downloadResult", function (url) {
    console.log('<a href="' + url + '">Download result file here</a>');
  });

  connection.on("onComplete", function (message) {
    console.log(message);
  });
}

我在一台机器上使用服务器和客户端进行了本地测试,一切正常。但自从部署测试以来,我收到了错误。 (Websocket 在服务器上激活。)

Postman 也可以建立与 websocket 的连接,只是我的客户端失败了。

我将不胜感激任何形式的帮助。预先感谢!

编辑: 我还尝试通过(here)描述的 SignalR 客户端替代方案连接到 SignalR。

async function connectToWebsocket(negotiations) {
  let token = encodeURIComponent(negotiations.connectionToken);
  let wssPath = `ws://<SERVERADRESS>/api/signalr/designautomation?id=${token}`;
  let ws = new WebSocket(wssPath);

  console.log(ws);
}

async function connectToSignalR() {
  $.ajax({
    url: "<SERVERADRESS>/api/signalr/designautomation/negotiate?negotiateVersion=1",
    contentType: "application/json",
    dataType: "json",
    headers: { "Access-Control-Allow-Origin": "*" },
    type: "POST",
    success: function (res) {
      console.log(res);
      connectToWebsocket(res);
    },
    error: function (error) {
      console.log(error);
    },
  });
}

结果还是一样。我收到了协商的响应,但无法连接到 websocket。

作为附加信息。我的“服务器”是 Azure-VM 上的 iis-express,具有通过 ngrok 转发的地址。

另一个编辑: 我关于使用 SignalR 的整个案例是运行一个 websocket 连接,autodesk-forge 服务器可以在完成我提交的任务时回调该连接,让他们知道下一个任务是什么。 我添加了Tag,也许这个方向的人遇到了同样的问题并可以给出提示。

还有另一个编辑: 我现在还尝试使用我能找到的最简单的示例(来自微软的 chatapp 示例)连接到远程服务器。 还是同样的问题。我在这里添加了整个控制台输出: console_output 我也很好奇我的 CORS 是否有问题。 但它的定义如每个工作示例中所述......

javascript c# signalr autodesk-forge ngrok
2个回答
2
投票

问题是由 ngrok 和可能的 CORS 引起的(如控制台输出中所述)。

在正确的方向推动之后,我尝试了另一个工具(Conveyor - VS Extension)将本地主机转发到网络。从远程客户端连接到 websocket 或任何其他传输方法绝对没有问题。

因此,对于遇到同样问题的任何人,尝试在 iis-express 中调试使用 ngrok 转发的 websocket 连接并收到 CORS 错误,请改用 Conveyor。 只要您不知道如何配置 ngroks CORS 处理(“http --host-header=rewrite”就不起作用)。

如果您知道如何配置 ngroks CORS 处理,我很乐意在评论中阅读它。


0
投票

我遇到了同样的问题,但在 iis 中启用 Web 套接字功能后,它起作用了。

iis设置

© www.soinside.com 2019 - 2024. All rights reserved.