Une bonne approche serait de créer un thread qui n'accepte que les nouvelles connexions. C'est là que vous avez une prise d'écoute. Ensuite, pour chaque connexion acceptée, vous disposez d'un nouveau socket connecté, ce qui vous permet de générer un autre thread, en lui donnant comme paramètre le socket connecté. Ainsi, votre thread qui accepte les connexions ne se bloque pas et peut se connecter très rapidement à de nombreux clients. Les threads de traitement traitent les clients, puis ils sortent. Je ne sais même pas pourquoi j'ai besoin de les attendre, mais si vous le faites, vous pouvez le faire d'une autre manière, en fonction du système d'exploitation et/ou des bibliothèques que vous utilisez (messages, signaux, etc.). utilisé).
Si vous ne souhaitez pas générer un nouveau thread pour chaque client connecté, alors, comme l'a suggéré Ben Voigt, vous pouvez utiliser select. C'est une autre bonne approche si vous voulez faire un seul thread. Fondamentalement, toutes vos prises seront dans un tableau de descripteurs de socket et en utilisant select vous saurez ce qui s'est passé (quelqu'un connecté, socket est prêt pour la lecture/écriture, socket déconnecté, etc) et agir en conséquence.
Voici un exemple Partiel, mais cela fonctionne. vous acceptez simplement les connexions dans acceptConnections(), qui engendrera alors un thread séparé pour chaque client. C'est là que vous communiquez avec les clients. C'est à partir d'un code Windows que je traîne, mais il est très facile d'être réimplémenté pour n'importe quelle plateforme.
typedef struct SOCKET_DATA_ {
SOCKET sd;
/* other parameters that you may want to pass to the clientProc */
} SOCKET_DATA;
/* In this function you communicate with the clients */
DWORD WINAPI clientProc(void * param)
{
SOCKET_DATA * pSocketData = (SOCKET_DATA *)param;
/* Communicate with the new client, and at the end deallocate the memory for
SOCKET_DATA and return.
*/
delete pSocketData;
return 0;
}
int acceptConnections(const char * pcAddress, int nPort)
{
sockaddr_in sinRemote;
int nAddrSize;
SOCKET sd_client;
SOCKET sd_listener;
sockaddr_in sinInterface;
SOCKET_DATA * pSocketData;
HANDLE hThread;
sd_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sd_listener) {
fprintf(stderr, "Could not get a listener socket!\n");
return 1;
}
sinInterface.sin_family = AF_INET;
sinInterface.sin_port = nPort;
sinInterface.sin_addr.S_un.S_addr = INADDR_ANY;
if (SOCKET_ERROR != bind(sd_listener, (sockaddr*)&sinInterface, sizeof(sockaddr_in))) {
listen(sd_listener, SOMAXCONN);
} else {
fprintf(stderr, "Could not bind the listening socket!\n");
return 1;
}
while (1)
{
nAddrSize = sizeof(sinRemote);
sd_client = accept(sd_listener, (sockaddr*)&sinRemote, &nAddrSize);
if (INVALID_SOCKET == sd_client) {
fprintf(stdout, "Accept failed!\n");
closesocket(sd_listener);
return 1;
}
fprintf(stdout, "Accepted connection from %s:%u.\n", inet_ntoa(sinRemote.sin_addr), ntohs(sinRemote.sin_port));
pSocketData = (SOCKET_DATA *)malloc(sizeof(SOCKET_DATA));
if (!pSocketData) {
fprintf(stderr, "Could not allocate memory for SOCKET_DATA!\n");
return 1;
}
pSocketData->sd = sd_client;
hThread = CreateThread(0, 0, clientProc, pSocketData, 0, &nThreadID);
if (hThread == INVALID_HANDLE_VALUE) {
fprintf(stderr, "An error occured while trying to create a thread!\n");
delete pSocketData;
return 1;
}
}
closesocket(sd_listener);
return 0;
}
Quel est le point de démarrer un fil et de le rejoindre immédiatement? –
Je pensais que join attend que le thread se termine? –
C'est le cas, ce qui signifie qu'un seul thread est en cours d'exécution à la fois, totalement vaincre le but. –