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

How to use SignalR to send data to a specific user?

我有一个通过 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 我是谁吗?

If you are using Azure SignalR Service:

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:

Groups 是向部分用户发送消息的最简单方法。如果要向某个用户发送消息,可以使用userId作为群组名称。

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

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

使用 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"
    }
  ]
}