如何使用SignalR向特定用户发送数据?

7

我有一个客户端使用SignalR接收消息,它能正常工作但更像是广播。我想发送消息给指定的客户端。在客户端上,我有一个userId,并且我按照以下方式设置了连接:

const userId = getUserId();

if (userId) {
    const beacon = new signalR.HubConnectionBuilder()
        .withUrl(`${URL}/api?userId=${userId}"`)
        .build();

    beacon.on('newMessage', notification => console.log);
    beacon.start().catch(console.error);
  }
};

在服务器端(使用JavaScript编写的Azure函数)我有一条消息和一个userId。对于我来说,问题是服务器如何知道哪个SignalR连接是发送给特定用户的?我能否以某种方式告诉SignalR我的身份?

2个回答

4
使用Azure SignalR服务和问题中的客户端代码,我能够让它工作。我使用了以下Azure函数来协商连接:
module.exports = async function (context, req, connectionInfo) {
  context.res.body = connectionInfo;
  context.done();
};

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "signalRConnectionInfo",
      "name": "connectionInfo",
      "userId": "{userId}",             // <----- IMPORTANT PART!
      "hubName": "chat",
      "direction": "in"
    }
  ]
}

还有一个发送消息给特定用户的功能:

module.exports = async function (context, req) {
  const messageObject = req.body;
  return {
    "target": "newMessage",
    "userId": messageObject.userId,
    "arguments": [ messageObject.message]
  };
};

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "signalR",
      "name": "$return",
      "hubName": "chat",
      "direction": "out"
    }
  ]
}

@leonheess 我怎样在客户端接收特定userID的消息?我在连接中传递了userId,格式为connection.qs = { 'userId' : '12345' }; 但没有帮助。 - user2107373
1
@user2107373,你是否像我一样在 signalRConnectionInfo 中传递了 "userId": "{userId}", - leonheess
那就是诀窍。我没有在 negotiate 的 function.json 中传递 userId。一旦我在 function.json 中添加了 "userId": "{userId}",问题就解决了。 - user2107373

3

如果您正在使用Azure SignalR服务

module.exports = async function (context, req) {
    context.bindings.signalRMessages = [{
        // message will only be sent to this user ID
        "userId": "userId1",
        "target": "newMessage",
        "arguments": [ req.body ]
    }];
};

一个用户ID可能映射到多个客户端连接(例如设备),请注意。

如果您需要向多个用户发送消息或自己托管SignalR:

是向用户子集发送消息的最简单方法。如果要向特定用户发送消息,可以使用userId作为组名。

决定哪个用户属于哪个组是服务器端的功能,因此您需要编写一些代码。

module.exports = async function (context, req) {
  context.bindings.signalRGroupActions = [{
    "userId": req.query.userId,
    "groupName": "myGroup",
    "action": "add"
  }];
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接