When you call accept(2) you can choose to retrieve the address of the client.
int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
You need to store those addresses and then send(2) to each what you need to send.
So the workflow should be something like this:
- Keep a list of connected clients. Initially the list is empty, of course
- When you accept a connection, push its details into that list (the address and the socket returned by
accept(2)). - When you need to send something to every client, simply walk the list and send it (using the stored socket)
The one tricky part is that socklen_t *restrict address_len is a value-result argument, so you need to be careful with that.