2012-02-10 4 views
0

Je suis désolé pour la simplicité de cette question, mais j'ai un problème ici. J'ai un programme client-serveur. Je ne sais pas auparavant combien de connexions viendront mais elles ne sont pas infinies. Et à la fin, après que toutes les connexions sont fermées, certains résultats sont sortis. Mais le problème que j'ai, c'est, accepter les connexions est dans une boucle infinie, comment est-il stopd pour sortir le résultat.arrêt d'un programme de serveur client

Merci

+4

pouvez-vous poster le code pour la boucle while? – Brian

Répondre

1

vous devez avoir une certaine forme de conditions pour sortir de la boucle vous, dans votre cas, un délai d'attente serait probablement le meilleur travail, ce qui signifie essentiellement, si vous ne recevez pas de nouveaux clients pour x secondes, vous arrêtez de chercher des clients, il en va de même pour toute erreur de connexion.

Rien de plus nécessite de regarder le code que vous utilisez.

+0

pensait à un délai d'attente ... merci –

1

La gestion EINTR sur l'erreur de accept(2) avec la fin du programme et en frappant ^C fonctionne habituellement.

0

Vous pouvez installer un gestionnaire pour le signal SIGTERM qui fixerait une variable globale volatile sig_atomic_t et tester cette variable dans la boucle de multiplexage (probablement autour poll ou select). Rappelez-vous que les gestionnaires signal ne peuvent pas appeler beaucoup de fonctions (seulement les async-signal-safe).

Attrayant joliment SIGTERM est prévu de la plupart des serveurs Linux ou Posix.

Vous pouvez envisager d'utiliser une bibliothèque de gestion des événements comme libev, libevent etc.

0

Bien que mon expérience est avec Windows NT la fonction « noms » sont ceux qui désignent threading génériques ou fonctions processus qui devraient être disponibles dans tous les multiples environnement de threading. Si le thread principal peut déterminer quand le thread enfant en question doit se terminer, il peut le faire en ayant la boucle de thread enfant sur un booléen - comme "terminate_conditon" - ou en terminant le thread à travers son handle.

// child thread 

terminate_condition=FALSE; 
while (!terminate_condition) 
{ 
    // accept connections 
} 
child_thread_done=TRUE; 
// output results 
exit_thread(); 

// main thread 

child_thread_done=FALSE; 
child_thread=create_thread (...); 

// monitor connections to determine when done 

terminate_condition=TRUE; 
while (!child_thread_done) 
{ 
    sleep (1); 
} 
// or maybe output results here? 
exit_process(); 

Cette solution de terminaison contrôlée nécessite qu'un seul thread écrit dans le booléen child_thread_done et que tout autre thread lit seulement.

Ou

// child thread 

while (1) 
{ 
    // accept connections 
} 

// main thread 

child_thread=create_thread (...); 

// monitor connections to determine when done 

kill_thread (child_thread); 
// output results 
exit_process(); 

La deuxième forme est messier car il tue tout simplement le fil de l'enfant. En général, il vaut mieux que le thread fils effectue une terminaison contrôlée, en particulier s'il a alloué des ressources (qui deviennent la responsabilité du processus dans son ensemble plutôt que du thread d'allocation).

S'il existe de nombreux threads enfants travaillant avec des connexions, un mécanisme de terminaison synchronisé est nécessaire: soit une structure avec autant de membres que de threads enfants (un thread de terminaison définit son booléen "terminé" sur true, se termine et le thread principal surveille la structure pour s'assurer que tous les enfants booléens «terminés» sont vrais avant de continuer) ou un compteur contenant le nombre de fils enfants qui fonctionnent (lorsqu'un enfant est sur le point de prendre le contrôle exclusif du compteur via un spinlock, le décrémente et le libère le verrou avant de se terminer: le thread principal ne fait rien avant que le compteur ne contienne zéro).