NetworkManager: How to respond to a specific client?

Short version of the question: In a local network game which is being handled by a NetworkManager, how can I have one client send a message to the server, and have the server send a message back just to that client?

Longer version: I’m new to networking code, and I guess I’m missing something. I have a class which inherits from NetworkManager, to handle local multiplayer. I have some data stored on the server, and when a new client connects, I want to send the data to the client in a Message. I originally had some code on the client side that, once a client had connected, would send a “data request” message to the server, with the client’s connectionID as part of the message. Upon receiving the “data request” message, the server would then do something like this:

void OnClientRequestDataMessage(NetworkMessage netMsg)
{
	var requestMessage = netMsg.ReadMessage<IntegerMessage>();
	int connectionId = requestMessage.value;

	DataMessage dataMsg = new DataMessage();
	// Copy the data that's stored on the server into the message
	ghostMessage._data = _serverData; 

	NetworkServer.SendToClient(connectionId, MSG_SERVER_SEND_DATA, dataMsg);
}

This worked for the local client (connectionId = 0) and the first remote client that connected (connectionId = 1) but broke for any subequent clients, since they would always send a connectionId of 1. I should have read the connectionId documentation more clearly! The connectionId I want to send to is the one the server uses, not the one the client sends.

So my question is, how do I find the right connectionId on the server to send the data to a given client?

I tried overriding OnServerConnect(NetworkConnection conn) and sending a message to conn.connectionId to get data to the client, but that doesn’t work. The client (at least in the case of the local client) is not yet fully connected at that point and so never receives the message. I could store the clientId and try sending a message at some point later (next frame?) but I don’t know how I can be sure when the client has finished connecting and can receive messages, and it also seems like it could introduce all sorts of horrible edge cases if two clients try to connect at the same time. I could sidestep the problem by just using NetworkServer.SendToAll but it seems like overkill to be sending data to clients which are already connected and don’t need to receive that data again. Surely there’s a straightforward way to do this?

I figured it out. Feel a bit stupid for not having seen it before. I don’t need the client to send its connectionId in the request message because the NetworkMessage that gets passed to the callback already contains the NetworkConnection with the correct connectionId. I was focussed on the content of the Message itself and forgetting about the NetworkMessage it arrives packaged in. So the server code to respond to a data request would just look like this:

 void OnClientRequestDataMessage(NetworkMessage netMsg)
 {
     DataMessage dataMsg = new DataMessage();
     // Copy the data that's stored on the server into the message
     ghostMessage._data = _serverData; 
 
     NetworkServer.SendToClient(netMsg.conn.connectionId, MSG_SERVER_SEND_DATA, dataMsg);
 }