Du coup j'ai pas compris comment le problème a été résolu, et en quoi c'est du à un Selector (ça fait beaucoup de code à lire
).
A la base je t'aurais dis de faire attention dans ton instruction chaînée d'être bien sûr que l'opérateur ' << ' retourne bien une référence vers ton sf::Packet quand tu l'utilises avec des types personnalisés.
Pour ta question plus générale d'échange de paquets, il n'y a aucun obstacle à ce que le serveur contacte un client sans avoir au préalable reçu un message de celui-ci. Il suffit que ton serveur connaisse la liste des clients (connectés ou non (UDP)), et qu'il leur envoi un paquet quand tu le veux.
Il y a beaucoup de façons de procéder. Tu peux envoyer ton paquet immédiatement quand le serveur décide qu'il doit envoyer quelque chose à tel client. Tu peux aussi créer une file de paquets sortants, qui sera traitée, soit en la vidant complètement lors d'un tour de boucle de ton programme, soit en envoyant le paquet du bout de la file à chaque tour (permet d'équilibrer les opérations, premier arrivé premier servi, mais la boucle doit tourner vite et sans interruption).
Soit encore en ayant un thread qui s'occupe d'envoyer les paquets à destination lorsque la file n'est pas vide, mais là c'est plus compliqué et probablement pas le plus performant.
C'est juste que selon la complexité de ton programme tu peux en arriver à désirer un gestion "centralisée" de l'échange de messages, plutôt que d'avoir des fonctions send() un peu partout dans le code. Par exemple créer une class Transaction qui contient le paquet à envoyer et l'adresse du destinataire (ou le pointeur vers le socket), mais qui reste en vie après l'envoi, et ne disparaît que lorsqu'elle a reçu la réponse attendue, et qu'elle la transmise où il faut. Elle ne doit évidemment pas être bloquante. Les Transactions sont dans un conteneur, vérifiées à chaque tour du programme, et en sont effacées lorsque leur job est fini.
Ce sont juste des idées générales. Et probablement pas les meilleures.