You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SignalR实现API事件触发通知时遇连接拒绝问题求助

解决SignalR连接拒绝错误及前端消息展示问题

Hey there! 看你现在卡在了SignalR连接拒绝(ERR_CONNECTION_REFUSE)的问题上,同时之前的前端代码也有小疏漏,我来一步步帮你理清解决思路:

一、先搞定当前的连接拒绝错误

这个错误的核心原因是你的SignalR服务端没有正确响应客户端的连接请求,你可以按以下步骤排查:

1. 确认服务端的SignalR路由配置是否正确

这是最容易忽略的点:

  • 如果是ASP.NET MVC 5及更早版本:在Global.asax的Application_Start方法里,必须添加SignalR的路由映射:
protected void Application_Start()
{
    // 其他配置...
    RouteTable.Routes.MapHubs(); // 一定要加这行!
}
  • 如果是ASP.NET Core版本:路由配置方式不一样,要在Startup.cs的Configure方法里指定Hub的路径:
app.UseSignalR(routes =>
{
    routes.MapHub<NotificationHub>("/notificationHub");
});

另外,Core版本里不能再用GlobalHost获取IHubContext了,要通过依赖注入:

public class NotificationHub : Hub
{
    private readonly IHubContext<NotificationHub> _hubContext;

    // 通过构造函数注入
    public NotificationHub(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }

    // 推荐把Send改成实例方法,或者在需要触发通知的地方直接注入IHubContext
    public async Task Send(string content)
    {
        await _hubContext.Clients.All.SendAsync("addMessage", content);
    }
}

2. 确认客户端请求的地址和服务端匹配

你控制台里的请求地址是http://127.0.0.1:8080/signalr/negotiate,要检查:

  • 你的服务端真的运行在8080端口吗?如果是IIS Express,默认端口可能不是这个,去项目属性里看看端口设置。
  • 如果是ASP.NET Core,SignalR的默认路由不是/signalr,而是你MapHub里配置的路径,这时候客户端连接代码要改成:
// Core版本的客户端连接写法
var conn = new signalR.HubConnectionBuilder()
    .withUrl("/notificationHub") // 对应服务端配置的路径
    .build();

3. 检查跨域配置(如果前端和API不在同一域名/端口)

如果你的前端页面和SignalR服务端不在同一端口或域名,必须配置跨域允许:

  • ASP.NET MVC 5:用Microsoft.Owin.Cors包,在Owin的Startup.cs里配置:
public void Configuration(IAppBuilder app)
{
    app.UseCors(CorsOptions.AllowAll);
    app.MapHubs();
}
  • ASP.NET Core:在Startup.cs的ConfigureServices里添加跨域策略:
services.AddCors(options =>
{
    options.AddPolicy("AllowAll",
        builder => builder.AllowAnyOrigin()
                          .AllowAnyMethod()
                          .AllowAnyHeader()
                          .AllowCredentials());
});

然后在Configure里启用:

app.UseCors("AllowAll");
app.UseSignalR(...);

二、前端消息展示的正确写法

你之前的前端代码有个关键缺失:没有启动连接!而且可以优化消息展示的方式,比如显示在页面里而不只是alert:

$(document).ready(function () {
    // SignalR 2.x(对应MVC5)的写法:注意Hub名是驼峰式的notificationHub
    var conn = $.connection.notificationHub;

    // 定义接收消息的方法,要和服务端调用的addMessage完全对应
    conn.client.addMessage = function (message) {
        // 把消息添加到页面的某个容器里,比如id为notificationList的ul
        $("#notificationList").append(`<li>新通知:${message}</li>`);
        // 保留alert用于测试也可以
        alert(message);
    };

    // 必须调用start()启动连接!之前的代码漏掉了这一步!
    $.connection.hub.start()
        .done(() => console.log("SignalR连接成功啦!"))
        .fail(err => console.error("连接失败:", err));
});

记得在页面里加个用于展示通知的容器:

<ul id="notificationList"></ul>

三、服务端触发通知的优化建议

你的onTick静态方法调用NotificationHub.Send的方式,在MVC5里可以用,但在Core里不行,更推荐的做法是在需要触发通知的地方直接注入IHubContext:

public class YourController : Controller
{
    private readonly IHubContext<NotificationHub> _hubContext;

    // 通过构造函数注入IHubContext
    public YourController(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async void onTick(Tick TickData)
    {
        if(TickData.InstrumentToken == buy.InstrumentToken)
        {
            // Core里用SendAsync,MVC5里用Clients.All.addMessage
            await _hubContext.Clients.All.SendAsync("addMessage", TickData.Bid.ToString());
        }
    }
}

最后总结下解决步骤

  1. 先确认服务端的SignalR路由配置是否正确,有没有加MapHubs(MVC5)或MapHub(Core)。
  2. 补上前端代码里的$.connection.hub.start()调用,启动连接。
  3. 检查服务端运行的端口和前端请求的端口是否一致。
  4. 如果跨域,配置好跨域允许规则。

内容的提问来源于stack exchange,提问作者user2695433

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:13