stevenjin 2024-09-07 16:51 采纳率: 99.5%
浏览 2
已结题

websocket或signalR消息发送到了服务器而不是客户端

1.环境asp.net core mvc .net7.0
2.在项目中使用websocket或signalR。
先使用发布的服务器打开了该网站,再用其他PC访问。发消息时,接收到消息的是服务器上的页面。
反之,关掉服务器的网站,就能在PC上接收到消息。如果网站上有多个tab标签页,也只有最早打开的那个tab页能收到消息。
以下是signalR的方式:

//服务端
try
{
    var builder = WebApplication.CreateBuilder(args);
   
  
   
    //跨域服务配置
    builder.Services.AddCors(options =>
    {
        options.AddPolicy("Cors", p =>
        {
            p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
        });
    });
    

    builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation();
  
    builder.Services.AddSignalR();//添加SignalR服务,需要添加到AddRazor后 
    builder.Services.AddSingleton<SocketConnectionManage>();
    builder.Logging.ClearProviders();
    builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Error);
    builder.Host.UseNLog();

    //builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);

    builder.Services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
    builder.Services.AddControllers().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
         
    });
    builder.Services.AddControllers().AddNewtonsoftJson(option =>
    {       
        option.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
    });


    app.Urls.Add("http://*:8081"); 
    app.UseCors("Cors"); 
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();//身份认证必须在静态文件之后,路由之后

    app.UseAuthorization();//身份授权

    app.UseResponseCaching();//启用服务器缓存 

    app.MapHub<MessagePushHub>("/messagePushHub");//启用SignalR服务
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    app.Run();
    NLogHelper.Trace("应用程序已运行");
}

catch(Exception exception)
{  
    NLogHelper.Error("Stopped program because of exception", exception);   
    throw;
}
finally
{   
    NLog.LogManager.Shutdown();
}

public class MessagePushHub : Hub
{
    private readonly SocketConnectionManage _onlineSocketClient;
    public MessagePushHub(SocketConnectionManage onlineSocketClient)
    {
        this._onlineSocketClient = onlineSocketClient;
    }
    public async Task onOpen(string userId)
    {
        string connectionId = Context.ConnectionId;
        _onlineSocketClient.AddSocket(userId, connectionId);
        Console.WriteLine($"客户端{userId},连接成功");
        await Task.CompletedTask;
    }
    public async Task onMessage(string message)
    {
        string connectionId = Context.ConnectionId;
        string userId = _onlineSocketClient.GetUserIdByConnectionId(connectionId);
        Console.WriteLine($"[服务端]=>接收到客户端{userId},发送的数据为:{message}");
        await this.Clients.Client(connectionId).SendAsync("ReceivePushMessage", message);
        await Task.CompletedTask;
    }

    /// <summary>
    /// 客户端连接成功
    /// </summary>
    /// <returns></returns>
    public override Task OnConnectedAsync()
    {
        return base.OnConnectedAsync();
    }

    /// <summary>
    /// 客户端断开
    /// </summary>
    /// <param name="exception"></param>
    /// <returns></returns>
    public override Task OnDisconnectedAsync(Exception exception)
    {
        string connectionId = Context.ConnectionId;
        string userId = _onlineSocketClient.GetUserIdByConnectionId(connectionId);
        Console.WriteLine($"客户端{userId},断开连接");
        _onlineSocketClient.RemoveSocket(userId);
        return base.OnDisconnectedAsync(exception);
    }
}

public class SocketConnectionManage
{
    private static ConcurrentDictionary<string, string> _sockets = new ConcurrentDictionary<string, string>();
    public void AddSocket(string userId, string connectionId)
    {
        _sockets.TryAdd(userId, connectionId);
    }
    public ConcurrentDictionary<string, string> GetClients()
    {
        return _sockets;
    }
    public void RemoveSocket(string userId)
    {
        if (IsExistsUserId(userId))
        {
            _sockets.TryRemove(userId, out var value);
        }
    }
    public string GetConnectionIdByUserId(string userId)
    {
        if (IsExistsUserId(userId))
        {
            string connectionId = _sockets.FirstOrDefault(t => t.Key == userId).Value;
            return connectionId;
        }
        return string.Empty;
    }
    public string GetUserIdByConnectionId(string connectionId)
    {
        if (IsExistsConnectionId(connectionId))
        {
            string userId = _sockets.FirstOrDefault(t => t.Value == connectionId).Key;
            return userId;
        }
        return string.Empty;
    }
    public bool IsExistsUserId(string userId)
    {
        return _sockets.Select(s => s.Key).ToList().Exists(t => t == userId);
    }
    public bool IsExistsConnectionId(string connectionId)
    {
        return _sockets.Select(s => s.Value).ToList().Exists(t => t == connectionId);
    }
}

//客户端
"use strict";

var connection = new signalR.HubConnectionBuilder()
                                                .withUrl("http://localhost:5000/messagePushHub")
                                                .withAutomaticReconnect()
                                                .build();

//Disable send button until connection is established
document.getElementById("btnLogin").disabled = true;

connection.start().then(function () {
    document.getElementById("btnLogin").disabled = false;
}).catch(function (err) {
    return console.error(err.toString());
});

connection.onreconnecting(error => {
    console.log("断线重连中...");
});

connection.onreconnected(connectionId => {
    console.log("重连成功...");

    //重新绑定用户连接
    var txtUserId = document.getElementById("txtUserId").value;
    connection.invoke("onOpen", txtUserId).then(function () {
    }).catch(function (err) {
        return console.error(err.toString());
    });

});

connection.on("ReceivePushMessage", function (msg) {
    var encodedMsg = "服务端=>向客户端推送的消息为:"+msg;
    var li = document.createElement("li");
    li.textContent = encodedMsg;
    document.getElementById("messagesList").appendChild(li);
});

document.getElementById("btnLogin").addEventListener("click", function (event) {
    var txtUserId = document.getElementById("txtUserId").value;
    connection.invoke("onOpen", txtUserId).then(function () {
        var li = document.createElement("li");
        li.textContent = "连接成功";
        document.getElementById("messagesList").appendChild(li);
        document.getElementById("btnLogin").disabled = true;
    }).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

document.getElementById("btnSendMessage").addEventListener("click", function (event) {
    var messageInput = document.getElementById("messageInput").value;
    connection.invoke("onMessage", messageInput).catch(function (err) {
        return console.error(err.toString());
    });
    var li = document.createElement("li");
    li.textContent = "客户端=>向服务端发送的消息为:"+messageInput;
    document.getElementById("messagesList").appendChild(li);
    event.preventDefault();
});
  • 写回答

2条回答 默认 最新

  • 一轮明月照丘壑 2024-09-07 16:52
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    根据你的描述和代码,问题可能在于你在服务器端将消息发送到了所有连接的客户端,包括正在发送消息的客户端。这就是为什么你在其他PC上接收到了消息,因为消息被发送到了所有连接的客户端,包括你正在操作的服务器上的客户端。当你关闭服务器上的网站时,没有客户端连接到服务器,所以你就不能再接收到消息了。

    为了解决这个问题,你需要确保你的服务器在发送消息时只发送到特定的客户端。这通常可以通过检查消息的接收者连接ID来实现。你可以在发送消息之前检查连接ID是否是你想要发送的目标客户端的连接ID。你可以使用SocketConnectionManage类的GetUserIdByConnectionId方法来获取连接ID对应的用户ID。这样你就可以确保只有特定的客户端可以接收到消息。修改后的onMessage方法可能如下:

    public async Task onMessage(string message, string connectionId)
    {
        string userId = _onlineSocketClient.GetUserIdByConnectionId(connectionId);
        if (userId != null) //检查是否是你想要发送消息的客户端
        {
            Console.WriteLine($"[服务端]=>接收到客户端{userId},发送的数据为:{message}");
            await this.Clients.Client(connectionId).SendAsync("ReceivePushMessage", message);
        }
        await Task.CompletedTask;
    }
    

    同时,确保你的前端代码正确地设置了连接ID和消息接收的处理。你可能需要修改前端代码以包含连接ID并将其发送到服务器,然后在接收到消息时检查是否是发给自己的消息。这样你就可以确保只有正确的客户端可以接收到消息。希望这个解答对你有所帮助!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 9月15日
  • 已采纳回答 9月7日
  • 修改了问题 9月7日
  • 修改了问题 9月7日
  • 展开全部

悬赏问题

  • ¥15 岛津txt格式文件转nirs格式
  • ¥15 石墨烯磁表面等离子体
  • ¥15 angular 项目无法启动
  • ¥15 安装wampserver,图标绿色,但是无法进入软件
  • ¥15 C++ MFC 标准库 加密解密解惑
  • ¥15 两条数据合并成一条数据
  • ¥15 Ubuntu虚拟机设置
  • ¥15 comsol三维模型中磁场为什么没有“速度(洛伦兹项)”这一选项
  • ¥15 electron 如何实现自定义安装界面
  • ¥15 关于#linux#的问题:子进程C运行“ls –l”命令,且显示“C运行ls-l命令”(语言-c语言)