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

SignalR客户端持续发送空对象消息的追踪与日志记录方案

针对ASP.NET MVC(.NET Framework 4.7.2)追踪客户端心跳消息的解决方案

1. 定义接收心跳的接口

首先需要创建一个MVC Action来接收客户端每10秒发送的空对象请求,ASP.NET MVC的模型绑定可以直接兼容空JSON对象:

[HttpPost]
public JsonResult KeepAlive([FromBody] object emptyObject)
{
    // 后续的日志记录、活跃用户更新逻辑写在这里
    return Json(new { success = true });
}

2. 记录活跃用户与心跳日志

在Action中获取用户标识(认证用户用User.Identity.Name,匿名用户用Session ID或客户端自定义UUID),同时记录心跳日志并更新活跃状态:

using System.Runtime.Caching;
using System.Diagnostics;

[HttpPost]
public JsonResult KeepAlive([FromBody] object emptyObject)
{
    // 获取用户唯一标识
    string userId = User.Identity.IsAuthenticated 
        ? User.Identity.Name 
        : Session.SessionID; // 匿名用户用SessionID,若需跨会话追踪可让客户端存UUID到Cookie

    // 1. 写入心跳日志(可替换为log4net、NLog等日志框架)
    string logContent = $"用户[{userId}]心跳时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}";
    Trace.WriteLine(logContent);

    // 2. 更新活跃用户缓存,设置过期时间(例如30秒,超过则判定为非活跃)
    var cache = MemoryCache.Default;
    cache.Set($"ActiveUser_{userId}", userId, DateTime.Now.AddSeconds(30));

    return Json(new { success = true });
}

3. 实现服务器向活跃用户推送消息

方案一:基于轮询的简单推送

客户端在发送心跳的同时,额外定期请求服务器获取未读消息,Action示例:

[HttpGet]
public JsonResult GetUnreadMessages()
{
    string userId = User.Identity.IsAuthenticated ? User.Identity.Name : Session.SessionID;
    // 从数据库/缓存中获取该用户的未读消息
    var messages = GetMessagesFromStorage(userId);
    return Json(messages, JsonRequestBehavior.AllowGet);
}

方案二:基于SignalR的实时推送(更高效)

ASP.NET MVC 4.7.2可集成SignalR 2.x实现长连接推送:

  1. 安装SignalR NuGet包:
Install-Package Microsoft.AspNet.SignalR
  1. 配置SignalR路由(新建或修改Startup类):
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(YourAppNamespace.Startup))]
namespace YourAppNamespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}
  1. 定义Hub类,整合心跳与推送逻辑:
using Microsoft.AspNet.SignalR;
using System.Runtime.Caching;

public class NotificationHub : Hub
{
    // 客户端调用此方法发送心跳
    public void ReportAlive()
    {
        string userId = Context.User.Identity.Name ?? Context.ConnectionId;
        var cache = MemoryCache.Default;
        // 缓存用户的连接ID,用于精准推送
        cache.Set($"ActiveUser_{userId}", Context.ConnectionId, DateTime.Now.AddSeconds(30));
    }

    // 服务器主动推送消息的静态方法
    public static void PushMessageToUser(string userId, string messageContent)
    {
        var cache = MemoryCache.Default;
        string connectionId = cache.Get($"ActiveUser_{userId}") as string;
        if (!string.IsNullOrEmpty(connectionId))
        {
            GlobalHost.ConnectionManager
                .GetHubContext<NotificationHub>()
                .Clients.Client(connectionId)
                .receiveMessage(messageContent);
        }
    }
}

客户端可直接调用SignalR的ReportAlive方法替代单独的空对象请求,同时监听receiveMessage事件接收推送。

4. 日志持久化(可选)

若需将心跳日志持久化到文件或数据库,以NLog为例,配置NLog.config:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <targets>
        <target name="heartbeatLog" xsi:type="File" 
                fileName="${basedir}/Logs/Heartbeat/${shortdate}.log"
                layout="${longdate} | ${message}" />
    </targets>
    <rules>
        <logger name="HeartbeatLogger" minlevel="Info" writeTo="heartbeatLog" />
    </rules>
</nlog>

在Action中使用NLog记录:

private static readonly NLog.Logger heartbeatLogger = NLog.LogManager.GetLogger("HeartbeatLogger");

[HttpPost]
public JsonResult KeepAlive([FromBody] object emptyObject)
{
    string userId = User.Identity.IsAuthenticated ? User.Identity.Name : Session.SessionID;
    heartbeatLogger.Info($"用户[{userId}]发送心跳");
    // 更新活跃用户缓存...
    return Json(new { success = true });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:05:07