Si on souhaite écrire un programme portable, le plus simple est d'utiliser select() avec des sockets bloquantes (ou non bloquantes pour une meilleure répartition de la charge du trafic et de meilleures performances).
L'exemple select.c utilise des sockets bloquantes.
Cette méthode était la préférée sous Windows 3.1, lorsque les threads n'existaient pas. On peut encore utiliser cette méthode avec des programmes type IHM, lorsqu'un second thread n'est pas nécessaire, ou bien que l'on ne veut pas se heurter aux problèmes induits par le multithread.
Le fonctionnement de cette API consiste à associer un message Windows utilisateur (WM_USER + xxx) avec une socket pour un type d'évènement voulu :
L'application rappele donc l'utilisateur par le biais de ce message Windows, le wParam et lParam permettant d'extraire la socket concernée ainsi que l'évènement et le cas échéant l'erreur.
On utilise les fonctions recv(), send(), connect(), accept(), closesocket() etc.. pour lire, écrire etc.. les données. C'est donc exactement le même principe qu'avec select().
l'utilisation de WSAAsyncSelect() fait basculer automatiquement l'application en mode non bloquant.
voir l'exemple wsaasyncselect.zip.
C'est le même principe que WSAAsyncSelect(), mais cette fois-ci, on associe un évènement Win32 (WSACreateEvent() ou CreateEvent()) avec la socket.
lorsque l'évènement Win32 associé à la socket est signalé, on utilise WSAEnumNetworkEvents() afin de déterminer de quel évènement socket (FD_READ, FD_WRITE) il s'agit, et le cas échéant l'erreur.
On fonctionne aussi en socket non bloquante.
voir l'exemple wsaevenselect.c.
C'est la voie à suivre pour réaliser des programmes capables d'accepter plusieurs centaines de connexions à la seconde. Cela ne fonctionne que sous NT (NT4 - 2000 - XP).
Pour plus de détails, voir ici
Comment détecter un changement d'adresse IP suite à une connexion modem par exemple :
L'exemple joint montre comment passer une socket à un autre process.