2010-10-21 6 views
1

Bonjour, Je travaille sur une tâche d'écriture de serveur client multithread. Jusqu'à présent, j'ai fait est d'ouvrir une socket dans un port et fourche deux thread pour écouter et écrire au client. Mais j'ai besoin de connecter deux types de clients au serveur et de les servir différemment. Ma question est quelle serait ma meilleure approche?Serveur client multithread

Je gère la connexion dans une classe qui a une boucle infinie pour accepter la connexion. Lorsque jamais une connexion est acceptée, la classe crée deux thread à lire et écrire au client? Maintenant, si je veux gérer un autre client de type différent, que devons-nous faire?

Dois-je ouvrir un autre port? ou est-il possible de desservir par le même port? Peut être s'il est possible d'identifier le type de client dans le socket que je peux gérer les messages différemment.

Ou suggérez-vous que ça?

  1. Fourchez deux threads pour deux types de client et surveillez la connexion entrante dans chaque thread dans un port différent.
  2. lorsqu'une connexion acceptait que chaque thread générait deux autres threads pour l'écoute et l'écriture.

veuillez faire une suggestion.

Répondre

0

Différents protocoles sont généralement gérés sur différents ports. Toutefois, vous pouvez gérer les deux types de clients sur le même port en négociant le protocole à utiliser. Cela peut être aussi simple que le client envoyant soit HELO ou EHLO pour demander l'un ou l'autre type de service.

4

Peut-être que vous obtiendrez une meilleure réponse d'un utilisateur Unix, mais je vais fournir ce que je sais.

Votre serveur a besoin d'un thread qui ouvre un socket d'écoute qui attend les connexions entrantes. Ce thread peut être le thread principal pour la simplicité, mais peut être un thread alternatif si vous êtes préoccupé par l'interaction de l'interface utilisateur, par exemple (dans Windows, ce serait une préoccupation, pas sûr d'Unix). On dirait que vous êtes au moins aussi loin.

Lorsque la prise «écoute» accepte une connexion, vous obtenez une prise «connectée» qui est connectée à la prise «client». Vous passeriez ce socket 'connecté' à un nouveau thread qui gère la lecture de et en écrivant à la socket 'connecté'. Ainsi, un changement que je suggérerais est de gérer le socket 'connecté' dans un seul thread, pas deux threads séparés (un pour la lecture, un pour l'écriture) comme vous l'avez fait. La lecture et l'écriture sur la même socket peuvent être effectuées en utilisant l'appel système select(), comme indiqué here. Lorsqu'un nouveau client se connecte, votre socket «écoute» vous fournira un nouveau socket «connecté», que vous passerez à un autre thread. À ce stade, vous avez deux threads - un qui gère la première connexion et un qui gère la deuxième connexion. En ce qui concerne les prises, il n'y a pas de distinction entre les clients. Vous avez simplement deux connexions ouvertes, une à chacun de vos deux clients.

À ce stade, la question est de savoir ce que signifie «les servir différemment». Si les clients sont supposés interagir avec le serveur de manière unique, cela doit être déterminé d'une manière ou d'une autre. Les interactions peuvent être déterminées en fonction de l'adresse IP du socket 'client', que vous pouvez interroger, mais cela semble arbitraire et est soumis à des changements de réseau. Il pourrait aussi être basé sur le bloc de données initial reçu du socket 'client' qui indique le type d'interaction requis.Dans ce cas, le thread qui gère le socket 'connected' peut lire le socket pour le type d'interaction attendu, puis remettre le socket à un objet de classe qui gère ce type d'interaction.

J'espère que cela aide.

1

Vous pouvez gérer la lecture-écriture sur une connexion client unique dans un thread. La solution la plus simple basée sur plusieurs-threads sera ceci:

// C++ like pseudo-code 
while (server_running) 
{ 
    client = server.accept(); 
    ClientHandlingThread* cth = CreateNewClientHandlingThread(client); 
    cth->start(); 
} 

class ClientHandlingThread 
{ 
    void start() 
    { 
     std::string header = client->read_protocol_header(); 
     // We get a specific implementation of the ProtocolHandler abstract class 
     // from a factory, which create objects by inspecting some protocol header info. 
     ProtocolHandler* handler = ProtocolHandlerFactory.create(header);   
     if (handler) 
      handler->read_write(client); 
     else 
      log("unknown protocol") 
    }  
}; 

Pour mieux échelle, vous pouvez utiliser un pool de threads, au lieu de fraie un nouveau thread pour chaque client. Il existe de nombreuses implémentations free thread poolfor C++.

while (server_running) 
{ 
    client = server.accept(); 
    thread_pool->submit(client); 
    cth->start(); 
} 

Le serveur pourrait être améliorée en utilisant un certain cadre qui met en œuvre le reactor pattern. Ils utilisent les fonctions select ou poll sous le capot. Vous pouvez utiliser ces fonctions directement. Mais pour un système de production, il est préférable d'utiliser un cadre de réacteur existant. ACE est l'un des kits d'outils C++ les plus connus pour le développement d'applications simultanées hautement évolutives.