utilisation de boost sockets, ai-je besoin d'un seul io_service?
avoir plusieurs connexions dans plusieurs threads différents.. je suis fondamentalement de faire une classe de base qui utilise boost/asio.php et le tcp trucs là..
maintenant, je lisais ceci: http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/tutorial/tutdaytime1.html
il est dit que "Tous les programmes qui utilisent asio besoin d'avoir au moins un io_service de l'objet."
donc, ma classe de base a une statique io_service (ce qui signifie qu'il y aura seulement 1 pour l'ensemble du programme et de tous les différents fils et connexions utilisent le même io_service objet)
ou faire de chaque connexion à son propre io_service?
grâce devant!
mise à jour:
OK donc en gros ce que je voudrais faire est une classe de base pour un client qui aura un socket n il.
Pour chaque prise, je vais avoir un thread qui toujours-reçoit et un autre thread que, parfois, envoie des paquets.
après avoir regardé ici: www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/reference/ip__tcp/socket.html (ne peux pas faire de lien hypertexte depuis im nouveau ici.. alors que de 1 hyperling par post), je peux voir que la classe socket, ce n'est pas thread-safe..
donc 2 questions:
1. Basé sur le design que je viens d'écrire, j'ai besoin 1 io_service pour toutes les prises de courant (sens d'en faire un membre de classe statique) ou, devrais-je en avoir un pour chaque?
2. Comment puis-je faire thread-safe pour le faire? dois-je le mettre à l'intérieur d'un "thread-safe "environnement" dans le sens de faire une nouvelle classe socket a mutex et des trucs qui ne laisse pas u d'envoyer et de recevoir en même temps ou vous avez d'autres suggestions?
3. Je devrais peut-être aller sur un asynch design? (ofc chaque prise de courant ont un autre fil, mais l'envoi et la réception serait sur le même thread?)
juste pour clarifier: im faire un tcp client qui se connecte à un grand nombre de serveurs.
ma question est que dois-je faire et pourquoi? seulement 1 pour tous ou l'un de chacune d'elles et pourquoi?
Faites-vous synchrone ou asynchrone io?
je utiliser un autre thread pour recevoir et mettre tout ça dans un thread-safe tampon si c'est votre question
utilisez-vous le
async_read
et async_write
ou read
et write
gratuit fonctions?OriginalL'auteur grich | 2010-11-02
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin pour décider d'abord d'un style de prise de communication que vous allez utiliser:
synchrone signifie que toutes les opérations de bas niveau sont de blocage, et généralement vous avez besoin d'un thread pour l'accepter, et ensuite threads (lire fil ou io_service) pour gérer chaque client.
asynchrone signifie que toutes les opérations de bas niveau sont non-blocage, et ici, vous avez seulement besoin d'un seul thread (io_service), et vous devez être capable de gérer les rappels quand certaines choses se passent (c'est à dire l'accepte, partielle écrit, la raison de lit etc.)
Avantage de l'approche 1, c'est que c'est beaucoup plus simple de code (??) que 2, mais je trouve que le 2 est plus flexible, et en fait avec 2, par défaut, vous avez un seul thread de l'application (à l'intérieur de l'événement rappels sont fait dans un thread séparé pour les principaux envoi thread), en baisse de 2 bien sûr, c'est que votre délai de traitement des hits de la prochaine opérations de lecture/écriture... bien sûr, vous pouvez faire des applications multi-thread avec la méthode 2, mais pas vice-versa (c'est à dire mono-thread avec 1) - d'où la souplesse...
Donc, fondamentalement, tout dépend de la sélection de style...
EDIT: mis à jour pour la nouvelle information, c'est assez long, je ne peux pas être pris la peine d'écrire le code, il y a beaucoup dans le coup de pouce docs, je vais simplement décrire ce qui se passe à votre avantage...
[thread principal]
- déclarer une instance de io_service
- pour chacun des serveurs sont en cours de connexion (je suis en supposant que cette information est disponible au départ), créer une classe (disons
ServerConnection
), et dans cette classe, créer un tcp::socket en utilisant le même io_service exemple à partir de ci-dessus, et dans le constructeur lui-même, appelezasync_connect
, NOTE: cet appel de la planification d'une demande de connecter plutôt que le lien réel de l'opération (ce qui n'arrivera pas à plus tard)- une fois tous les
ServerConnection
objets (et leurs async_connects en file d'attente), appelrun()
sur l'instance de io_service. Maintenant, le thread principal est bloqué distribution des événements dans le io_service file d'attente.[asio fil] io_service par défaut a un thread dans lequel des événements programmés sont invoquées, vous n'avez pas de contrôle sur ce fil de discussion, et de mettre en œuvre un "multi-thread" programme, vous pouvez augmenter le nombre de threads que la io_service utilise, mais pour le moment le bâton avec un, il fera de votre vie simple...
asio va appeler des méthodes de votre classe ServerConnection selon laquelle les événements sont prêts à partir de la date prévue de la liste. Le premier rendez-vous en file d'attente (avant d'appeler run()) a été
async_connect
, maintenant asio vous rappellera lorsqu'une connexion est établie à un serveur, en général, vous mettez en place unehandle_connect
méthode qui sera appelée (vous passez à la méthode dans lesasync_connect
appel). Surhandle_connect
, tout ce que vous avez à faire est de planifier la prochaine demande - dans ce cas, vous voulez lire certaines données (éventuellement à partir de cette prise), de sorte que vous appelezasync_read_some
et passer dans une fonction, d'être informé lorsqu'il existe des données. Une fois cela fait, la principale asio dispatch thread va continuer de dispatching d'autres événements qui sont prêts (ce qui pourrait être les autres demandes de connexion ou même laasync_read_some
les demandes que vous avez ajouté).Disons que vous avez appelé parce qu'il existe des données sur un serveur de sockets, c'est passé à vous via votre gestionnaire pour
async_read_some
- vous pouvez ensuite traiter ces données, procédez comme vous le devez, mais et c'est le plus important - une fois cela fait, le calendrier de la prochaineasync_read_some
, de cette façon asio apporter davantage de données qu'il devient disponible. REMARQUE TRÈS IMPORTANTE: si vous n'avez plus de planifier les demandes (c'est à dire la sortie de l'gestionnaire sans la queue), puis le io_service va manquer des événements de l'expédition et de la course() (qui vous a appelé dans le thread principal) prendra fin.Maintenant, comme pour l'écriture, c'est un peu plus compliqué. Si toutes vos écritures sont fait aussi partie de la manipulation de données à partir d'un appel read (c'est à dire dans le pilote asio fil), alors vous n'avez pas besoin de vous soucier de verrouillage (à moins que votre io_service a plusieurs threads), d'autre dans votre méthode d'écriture, ajouter les données dans une mémoire tampon, et de planifier un
async_write_some
demande (avec un write_handler qui sera appelée lorsque la mémoire tampon est écrit, que ce soit partiellement ou totalement). Lorsque asio poignées de cette demande, il invoquera votre gestionnaire une fois les données écrites et vous vous avez l'option d'appelerasync_write_some
encore si il n'y a plus de données dans la mémoire tampon ou si aucun, vous n'avez pas eu à se soucier de la planification d'une écriture. À ce point, je vais parler de technique, de considérer le double buffering - je vais en rester là. Si vous avez complètement différent de ce thread qui est en dehors de la io_service et que vous voulez écrire, vous devez appeler laio_service::post
méthode et de passer d'une méthode à exécuter (dans votreServerConnection
classe) avec les données, la io_service va alors appeler cette méthode quand il peut, et à l'intérieur de cette méthode, vous pouvez alors en mémoire tampon les données et éventuellement appelasync_write_some
si une écriture est actuellement pas en cours.Maintenant, il y a une chose TRÈS importante que vous devez être prudent sur, vous ne devez JAMAIS l'annexe
async_read_some
ouasync_write_some
si il y a déjà un en cours, c'est à dire, disons que vous avez appeléasync_read_some
sur un socket, jusqu'à ce que cet événement est invoqué par l'asio, vous ne devez pas programmer un autreasync_read_some
, sinon vous aurez beaucoup de conneries dans vos tampons!Un bon point de départ est l'asio chat client/serveur que vous trouverez dans l'élan docs, il montre comment la async_xxx méthodes sont utilisées. Et de garder cela à l'esprit, tous les async_xxx appels de retour dans un délai de quelques dizaines de microsecondes), donc il n'y a pas blocage opérations, tout se passe de manière asynchrone. http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/chat/chat_client.cpp, est l'exemple que je faisais référence.
Maintenant si vous trouvez que les performances de ce mécanisme est trop lent et que vous souhaitez avoir de filetage, de tout ce que vous devez faire est d'augmenter le nombre de threads qui sont à la disposition des principaux io_service et la mise en place de verrouillage en lecture/écriture méthodes de ServerConnection et vous avez terminé.
Essayez de ne pas penser du point de vue des threads, au lieu de cela, mise à jour de la question ci-dessus avec ce que vous avez l'intention de le faire, comment voulez-vous que ce serveur pour travailler? Peut-être plus facile de répondre alors...
Je ne vais pas faire une rupture, je suis en train de faire un client qui se connecte à un-beaucoup de serveurs. De toute façon j'ai édité ma question pour clarifier tout mieux, Tnx.
Tnx beaucoup, mais je n'ai pas compris certaines parties de ce que vous avez écrit. La première chose d'abord, certains de mes écrire serait comme une réponse à l'ensemble des données reçues, et qu'il ne sera pas en tant que répondre et juste au hasard de l'écriture. je n'ai pas compris le double tampon chose que vous offert.. je veux écrire, je l'appelle
io_service::post
avec une méthode deServerConnection
(appelons celasendMsg
).. etsendMsg
doit appelerasync_send
(pourquoi u ne utilisationasync_write_some
btw?) et qui permettra de faire un thread-safe opération? et avant d'appelerasync_send
je devrais verrouiller et après je devrais débloquer? que dire de l'attente?salut m8 u peut lire mon dernier commentaire et merci de répondre :)? Tnx
OriginalL'auteur Nim
Pour les opérations asynchrones, vous devez utiliser une seule
io_service
objet pour l'ensemble du programme. Que ce soit un membre statique d'une classe, ou instancié ailleurs, il est à vous. Plusieurs threads peuvent invoquer sonrun
méthode, c'est décrite dans Inverse de la réponse.si vous avez des gestionnaires qui ne sont pas thread-safe, lire à ce sujet brins.
io_service
peut se bloquer les uns les autres. Dans mon cas, j'ai eu deux fils, tous deux de l'ajout d'un protocole TCP lire, et un délai de la minuterie, de sorte que le partagéio_service
objet a 4 achèvement des gestionnaires à gérer. Cela a provoqué une lecture à bloquer sur les autres de le lire, même si ils ne partagent pas une prise de courant. Le problème a été résolu en utilisant par threadio_service
objets, chaque traiter qu'avec un seul de lecture et d'un délai d'attente.OriginalL'auteur Sam Miller
La io_service est ce qui appelle toutes les fonctions de gestionnaire pour vous les connexions. Donc, vous devriez avoir une course de fil afin de répartir le travail entre les threads. Voici une page d'expliquer la io_service et fils:
Fils et Boost.Asio
Je vois une contradiction entre votre réponse et la doc est lié à. Le doc a dit que
run()
peut être appelée par plusieurs threads pour configurer un pool de threads. Comme je comprends que c'est sur plusieurs appels d'une instance de la méthode et non sur plusieurs instances.OriginalL'auteur Inverse