12
votes

Mon serveur devrait-il utiliser à la fois TCP et UDP?

J'écris une application client / serveur et je ne trouve vraiment pas de guides qui correspondent à mon besoin. Le faire seul me conduit à de nombreux défauts de conception avant que j'ai même commencé. Par exemple, le serveur doit mettre à jour chaque client quant à son état plusieurs fois chacun seconde. J'ai supposé que je ne pouvais pas mettre à jour chaque client individuellement, mais les émissions UDP devraient résoudre ce problème. Mais j'ai toujours besoin d'un canal TCP pour communiquer de manière fiable avec chaque client pour des choses comme: Messages de discussion, entrée utilisateur, etc.

Recherche de ce sujet Il semble qu'il soit possible qu'un serveur utilise les deux protocoles simultanément - mais seulement possible (non sensible). Personne ne suggère une telle approche, en fait, je me rassemble de Cet article que c'est plutôt mauvais de Utilisez les deux.


Maintenant, je suis très confus quant à la manière dont je devrais gérer des données sur mon serveur. Sauf si j'ai complètement mal compris quelque chose à propos de la perte de paquets, je souhaite garantir que la saisie de l'utilisateur résultant de «paquets de demande de serveur-requier» ne soit pas perdue. Chaque réponse sur le point de garantir la livraison avec UDP, sans échec, utilisez TCP. Ce qui est plus frustrant, c'est que chaque programme serveur / client que je puisse imaginer à tout le moins besoin de certains de ses messages garantis (par exemple, des messages de déconnexion de «déconnexion de l'instance».

Devrais-je utiliser UDP, TCP, à la fois ou que je pense juste à penser complètement à ce sujet?


1 commentaires

Je vais juste signaler Kyronet github.com/esotericsoftware/kryonet qui est une bibliothèque pour les jeux qui utilise TCP et UDP, et le rend beaucoup plus simple. Enet ENET.BESPIN.ORG est une bibliothèque pour implémenter un calque sur UDP pour vous permettre d'envoyer fiable / peu fiable données en même temps avec la même socket. Il y a aussi une implémentation Java si vous regardez. Je n'en ai utilisé aucun de ceux-ci, je ne peux donc pas y avoir d'aide. Il n'y a rien de mal à l'une ou l'autre approche.


6 Réponses :


6
votes

.. Mais les émissions UDP doivent résoudre ce problème

diffusion de diffusion uniquement à l'intérieur d'un réseau local et de la multidiffusion correspondant à la prise en charge de l'infrastructure - non triviale.

En dehors de cela: il n'y a pas de règle générale pour "..witing d'une application client / serveur ...". Les méthodes de communication et les protocoles dépendent fortement du boîtier d'utilisation et peuvent aller de simples paquets UDP ou TCP aux architectures de passage sophistiqués de messages avec des garanties de fiabilité et de temps réel, etc.

Ainsi, ce que vous devez faire dépend de ce que vous essayez d'atteindre, que vous n'avez pas spécifié suffisamment détaillé.


6 commentaires

Diffuser le travail uniquement à l'intérieur d'un réseau local Un serveur ne diffusera jamais aux clients? J'utiliserai toujours UDP (pour la vitesse) pour envoyer des mises à jour à chaque client individuellement, puis. Alors, que dois-je faire pour que mes packages envoient du client au serveur? (Ceux-ci ne devraient pas être perdus, devraient-ils ??)


Ce que j'essaie d'atteindre est une simple communication, honnêtement. Les clients doivent être en mesure de demander des données sur le serveur, comme dans toutes les applications client / serveur trivial. Si le serveur ne parvient pas à répondre à une entrée utilisateur, l'utilisateur ne doit pas demander à nouveau car le paquet aurait pu être perdu arbitrairement. Le client doit supposer qu'il existe des problèmes de réseau et à nouveau à nouveau au serveur (plusieurs demandes au serveur à partir de l'entrée utilisateur unique). Tout comme si j'avais utilisé TCP. Mais pour la mise à jour, j'ai besoin de udp, non?


@ user2651804: juste pour corriger certaines de vos hypothèses: UDP et TCP ne sont que des méthodes de transport et vous pouvez utiliser les deux sens (c'est-à-dire que l'utilisation de TCP pour les mises à jour est possible). UDP n'est pas nécessairement plus rapide, mais la latence peut être inférieure au coût de la fiabilité. Je recommande d'examiner les scénarios de client / serveur existants comme HTTP, qui utilise uniquement TCP.


La question peut sembler stupide, mais comment est-ce que je "regarde"? Je pense que vous avez raison que je fais de nombreuses hypothèses fausses .. Mais je ne sais pas où chercher des informations plus précises. Mais http est un transfert unique d'un fichier, correct? Il n'a aucune utilité pour UDP. Pouvez-vous corriger mon hypothèse que la plupart des applications de serveur / client nécessiteront TCP (ou une autre façon de garantir des messages sont livrées) et que simultanément , mais contraire, certaines de ces volontés Profitez des messages autonomes (UDP) et utilisez-les donc aussi?


@ user2651804: http est un protocole de demande / réponse et peut avoir plusieurs demandes / réponse dans une seule connexion TCP. SMTP (Mail), FTP, IMAP, ... Toutes utilisent TCP uniquement. UDP est principalement utilisé par une application en temps réel comme RTP, RTSP (audio / vidéo en temps réel), etc., et uniquement parce que dans ces cas une petite latence est requise et une perte de paquets acceptée. Dans certains cas, UDP et TCP peuvent être utilisés (DNS, SIP) en fonction du boîtier d'utilisation exact. Encore une fois, tout est question d'utiliser le cas d'utilisation et la plupart des applications client / serveur utilisent TCP car la plupart des cas d'utilisation comprennent la condition de fiabilité.


@ user2651804: Je vous recommanderais de créer une conception initiale de votre demande indépendante de la question si UDP ou TCP est préférable, mais modélisez simplement les communications. Et vous pouvez ensuite décider plus tard quelles communications sont effectuées par UDP et qui sont effectuées par TCP en fonction des avantages et des inconvénients de chacun de ces protocoles.



16
votes

permet d'obtenir des faits sur la table:

  • UDP n'est pas fiable. Jamais.

  • Dans certaines circonstances, UDP peut être particulièrement pertinent; par exemple. S'il existe une congestion du réseau, la limitation de taux ou le profilage de la circulation, ou si la taille du message UDP est plus grande que la MTU.

  • La diffusion UDP fonctionne uniquement sur votre segment de réseau local. Les routeurs Internet ne permettent généralement pas aux émissions de se propager plus loin que cela. Qui limite vraiment son utilité.

  • MultiCast UDP peut être une possibilité, sauf que cela a tendance à être bloqué aussi.

    Cela vous laisse probablement deux possibilités principales:

    • Messagerie point à point UDP de votre serveur à chacun des clients.
    • TCP du serveur à chacun des clients.

      Une autre possibilité est une sorte de communication de maille entre pairs à égale à l'aide de UDP ou de TCP, mais qui devient vraiment compliqué. N'allez pas là-bas à moins que vous n'ayez vraiment besoin de, et savez vraiment ce que vous faites.

      Donc à votre question.

      Devrais-je utiliser UDP, TCP, à la fois ou que je pense juste à penser complètement à ce sujet?

      Je recommande d'utiliser TCP entre le serveur et chaque client, car il est le plus simple. Pour simplifier encore plus loin, utilisez plusieurs connexions TCP par client afin d'éviter la complexité du multiplexage de plusieurs "conversations" une seule douille.

      La performance du réseau ne sera pas optimale, mais cela pourrait bien être assez bon votre application. Et je doute que c'est la partie de votre application où vous souhaitez dépenser tout votre temps de développeur.

      Lorsque vous arrivez au point d'avoir une application de travail (côtés client et serveur) et que vous l'utilisez, vous pouvez trouver (ou non!) que la mise en réseau est un goulot d'étranglement important et une cause d'insatisfaction de l'utilisateur. Ensuite, vous envisagez d'optimiser les communications dans la version 2.0 de votre application.

      Lorsque vous arrivez à implémenter la version 2.0 (ou 3.0 ...) pour répondre à l'évolutivité, vous devrez déplacer un moyen de dépendance sur un seul serveur. Mettez simplement, si vous avez n clients, et N continue d'augmenter, alors à un moment donné, un seul serveur ne sera pas capable de faire face. D'autres choses dans la conception de l'application peuvent également être problématiques. Par exemple, dans une application de jeu, vous ne pouvez pas envoyer de mises à jour continues sur chaque joueur à tous les autres joueurs ... où le nombre de joueurs continue de croître. Mais notez que ces problèmes sont largement indépendants des protocoles de réseau que vous utilisez.


12 commentaires

Je n'avais pas reconnu la distinction entre diffusion et multidiffusion . Les sentiers Oracle ne parlent que de multidiffusion et ne font pas de tels avertissements.


Voici la chose: je suis capable d'utiliser TCP et UDP pour écrire des applications de travail. Vous faites l'hypothèse que je ne veux pas passer mon temps à ce sujet, mais c'est exactement ce que je veux. Je veux le faire "la bonne façon", même si je me rendrais compte qu'il n'y a pas de ce type. Mais je dois insister sur le fait qu'il y a une manière générale de le faire correctement. Ma candidature ne sera jamais utilisée par plusieurs personnes simultanément. Mais la conception devrait être telle qu'elle pourrait!


Lorsque mes préoccupations se développent au-delà d'établir simplement des connexions entre client et serveur, je rencontre le problème comme décrit dans ma réponse. Vous semblez avoir pensé que j'ai supposé que UDP pourrait être fiable. Permettez-moi de clarifier (parce qu'une grande partie de mon problème pourrait être un malentendu là-bas). Les datagrammes peuvent être écrits de telle sorte qu'ils imitent le protocole TCP - avec des informations d'en-tête sur quel numéro il est, ACK, etc. C'est ce que je veux dire sur la livraison avec UDP.


Eh bien, franchement, si vous êtes prêt à passer du temps dessus, alors ... faites-le. Essayez toutes les alternatives et faites les expériences d'échelle, et cela vous dira ce qui est le meilleur. Nous ne pouvons pas vous donner des conseils fiables détaillés sur lesquels des alternatives vont fonctionner mieux pour vous parce que cela dépend d'un tas de variables ...


"Mais je dois insister sur le fait qu'il existe une manière générale de le faire correctement." - pas correct. Il y a beaucoup de façons qui pourraient être la meilleure façon, mais cela dépend vraiment des détails de la demande ... et de vos critères "meilleurs".


Je dois supposer aveuglément que je vais complètement mal à propos de quelque chose. Sinon, il y aurait des informations que je rechercherais sur Internet. Je ne sais pas où je vais mal, cependant. Je pourrais faire ce que je veux faire ce que je veux faire: utilisez les deux protocoles simultanément, cela résoudrait tous mes problèmes: et je ne voudrais pas expérimenter que je le faisais mal.


Oui ... Votre erreur pense qu'il existe une vraie solution. La raison pour laquelle vous ne pouvez pas trouver utiliser Google est ... ça n'existe pas.


J'affirme que presque toutes les applications serveur / client ont besoin d'au moins certaines informations échangées de manière fiable. Est-ce incorrect?


Pour certaines significations de "presque tous", oui c'est correct.


Vous dites que je ne peux pas envoyer trop d'informations à chaque client, bien sûr, et que ces problèmes sont indépendants de ce que le protocole est utilisé. Mais si les informations que j'envoies ne doivent pas nécessairement être livrées (ce n'est pas le cas; dans l'espoir que cela me permettra d'envoyer plus), j'utiliserai UDP pour mettre à jour les clients ... sur Certains choses. N'est-ce pas correct?


Laissez-nous Continuer cette discussion en chat .


"Pour simplifier encore plus loin, utilisez plusieurs connexions TCP par client afin d'éviter la complexité du multiplexage de plusieurs" conversations "une seule douille." Pourquoi cela devrait-il être plus simple? En fait est plus clair et facile à manier si vous utilisez une connexion par client avec un protocole bien défini. Cependant, il est très inefficace, il doit envoyer de nombreux messages dans une seconde et établir chaque fois qu'une connexion TCP ne pouvait pas fonctionner simplement parce que parfois et dans certains pays atablir une connexion prend une demi-seconde, cela signifie que dans certaines circonstances, il n'enverra que deux ou trois messages dans une seconde



0
votes

Même principe que vous demandez est utilisé dans les serveurs DNS. Le DNS utilise normalement UDP pour transférer rapidement (Principe du protocole UDP), mais non fiable. TCP est plus lent (avec acks et charge utile), mais fiable. Donc, lorsque je rite ci-dessous, utilisez les deux distingués par la charge utile.

de DNS BIND Documentation:

Normalement, les requêtes ordinaires utilisent UDP et les transferts de zone utilisent TCP.

Cependant, DNS limite les requêtes et les réponses UDP à environ 500 octets. Si Une réponse serait plus grande que cela, le serveur renvoie jusqu'à 500 octets et définit le drapeau "tronqué". Le client est alors censé effectuer la même requête à nouveau à l'aide de TCP, ce qui est presque illimité dans La taille de la réponse qu'il peut envoyer ...

Si vous voulez mettre à jour tous les serveurs en une fois, enregistrez-les à la multidiffusion et par un processus que vous communiquez avec vous tous les serveurs clients. C'est de nouveau peu fiable, mais rapide. https://fr.wikipedia.org/wiki/ip_multicast Donc, vous créez un serveur, auxquels les partenaires de multidiffusion seront enregistrés et écoutez-les. Pour être sûr que vous détectez que les datagrammes UDP tombent sur l'itinéraire, chaque fichier Datagramme UD a son numéro d'identification. Assurez-vous également de recevoir des datagrammes dans des commandes différentes dans lesquelles vous les envoyez, de sorte que la mémoire tampon ou la file d'attente doit être utilisée, calculant le bon ordre.

espère que cela aide.


0 commentaires

1
votes

Oubliez les protocoles de diffusion, ils ne fonctionnent tout simplement pas car quelqu'un a déjà écrit. Vous devez livrer votre message à chaque client unique, faire une classe STETCHANGEDISPATCHER ou quelque chose comme ça.

UDP n'est pas fiable mais est plus rapide que TCP compte tenu de manière particulièrement qu'il n'y a pas de poignée de main. La poignée de main est non seulement lente, mais aussi une petite bande passante consommant de manière particulièrement lorsque vous devez établir une connexion avec beaucoup de clients.

Utiliser à la fois UDP et TCP, ce n'est pas si mal, beaucoup de programme célèbre adopte cette approche. Par exemple, BitTorrent peut utiliser à la fois des protocoles: UDP pour communiquer avec suivi et gérer le DHT et le TCP pour transférer le morceau des fichiers. C'est mon explication sur leur choix: le traqueur ou le DHT est interrogé périodiquement, cela signifie que, en une journée d'utilisation, vous pouvez mettre à jour votre tracker des centaines de fois, si parfois, cela ne fonctionnait pas, n'est pas une grosse affaire parce que vous êtes Mise à jour de votre traqueur La prochaine fois de toute façon (la même idée est dans le protocole DNS, vous envoyez votre demande via UDP, si vous ne recevez pas de réponse dans un délai raisonnable, vous venez de renvoyer la demande). Le protocole TCP doit plutôt être utilisé pour le transfert de fichier car vous préférez être plus lent, mais vous voulez une fiabilité absolue.

Une autre application célèbre qui utilise les deux protocoles est Skype, mais pour des raisons différentes. Les vidéocallons sont UDP, c'est-à-dire que le protocole TCP lors de la réception d'un mauvais paquet s'arrête et demandez à nouveau le paquet, cela nécessite une heure. Il est donc préférable de ne pas arrêter l'appel, mais recevoir et traiter un mauvais paquet. C'est pourquoi, dans Skype, vous recevez parfois une mauvaise vidéo ou un audio incompréhensible, vous pouvez recevoir la vidéo tel qu'il est enregistreur, mais il est trop lent. TCP est utilisé pour d'autres choses telles que l'envoi de fichiers.

Vous devez donc envoyer des messages à beaucoup de clients plusieurs fois par seconde. Je n'établirais pas une nouvelle connexion TCP chaque message. À mon avis, vous avez ces deux options:

  1. Envoyez le changement d'état de chaque serveur via UDP si et seulement si vous pouvez vous permettre une perte de données
  2. Établissez la connexion one TCP pour chaque client et avec cette connexion Envoyez toute la modification de l'état du serveur, de fermer la connexion lorsque le client déconnecte

    Un protocole célèbre qui utilise deux connexions TCP est FTP, vous disposez d'une connexion pour envoyer des commandes et de recevoir des réponses au serveur et à une connexion pour envoyer et recevoir des fichiers, rappelez-vous que vous n'établissez pas de connexion chaque commande même si le Les commandes peuvent être envoyées très espacées dans le temps (sûrement plus que plusieurs fois dans une seconde) pour éviter trop de poignées de main. Vous avez beaucoup de modèles que vous pouvez suivre, mais que vous pouvez suivre que les protocoles de test sont chers (vous avez besoin de beaucoup de temps et vous aurez peut-être besoin de plus de 10 ordinateurs pour voir si tout fonctionne) alors réfléchissez bien avant de commencer le codage, sur Internet, vous pouvez trouver certains Méthodes mathématiques Pour calculer la performance de votre protocole et la bande passante, mais ils ne sont pas très simples. Bonne chance.


5 commentaires

Vous mentionnez Skype. TCP est utilisé pour envoyer des fichiers. Ne serait-il pas également utilisé pour envoyer des messages? Ou pour «démarrer» l'appel ou demander quelque chose d'autre du serveur avec des entrées utilisateur? C'est ma confusion. Bien que certaines applications puissent évidemment bénéficier d'UDP, quelles applications peuvent être possibles sans TCP? Vous dites que c'est pas si mal pour utiliser les deux protocoles. Que probablement signifie que je ne devrais pas le faire. Que devrais-je faire? Je bénéficie d'UDP. Si les clients ne sont pas mis à jour, ils seront la prochaine fois de toute façon - comme vous le dites. Mais évidemment, il doit être de TCP. Lorsque le client essaie de mettre à jour l'état du serveur.


En fait, pouvez-vous mentionner une application qui utilise uniquement UDP, puis nous pouvons réduire le problème de là.


Je l'ai déjà mentionné, le protocole DNS utilise uniquement UDP et c'est un protocole dans la couche d'application, mais je comprends que c'est un cas très particules. Bien sûr, si vous ne pouvez pas vous permettre une perte de données, vous devez utiliser TCP, mon point est que ce n'est pas une mauvaise pratique en utilisant les deux protocoles (et ce n'est pas plus difficile ou coûteux). Il vous suffit de comprendre si vous pouvez admettre la perte de données et où vous pouvez l'admettre. User2651804 a fait un commentaire intéressant que je suis totalement d'accord avec la réponse ci-dessus


«Si je ne peux pas payer la perte de données, je dois utiliser TCP '. Eh bien, voulez-vous dire que les données sont perdues dans le protocole DNS? Pour éviter les mauvaiserstanding, je vais simplement expliquer ma conception du protocole DNS: je demande à mon navigateur de localiser un serveur Web. Point final. Donc, vous dites que je demande utiliser UDP. Mais je prétend que si j'ai une connexion Internet et que le serveur Web est en ligne et capable de gérer la demande - je vais obtenir une réponse. C'est ce que j'appelle "communication fiable" dans ma question. L'entrée de l'utilisateur ne sera pas perdue. Il me semble donc que le protocole DNS utilise UDP pour atteindre ce que fait TCP. (Renvoyer des paquets).


Comme chaque réponse dans ce thread dit: Stackoverflow.com/Questtions/15629329/... Utilisez TCP. Pas udp.



0
votes

Si c'est un jeu client / serveur comme jeu d'action, je vous recommande TCP pour l'interface utilisateur, vous ne voulez pas perdre les données des utilisateurs, mais dans le jeu, vous ne pouvez pas vous permettre la communication dans TCP dans un jeu multijoueur rapide.

Parce que perdre des informations "Certaines" n'est pas si mauvaise dans un jeu d'action, donc je recommanderais UDP en jeu, ou où vous avez besoin d'une communication très rapide.

Mais si ce n'est pas un jeu qui a besoin d'une communication rapide, je vous recommanderais TCP.


1 commentaires

Je suis d'accord. Dans un jeu d'action, il peut être utile d'utiliser UDP. Et l'entrée de l'utilisateur peut ne pas être perdue. Et donc je pouvais juste aller droit et utiliser les deux protocoles. Qui me semble évident. Les gens découragent cela en général.



0
votes

Il me semble que vous pensez à une méthode fiable pour la communication client / serveur, qui sera comme la diffusion sans la communication TCP / IP aérienne.

Je peux aussi vous faire appel à la messagerie. Créez un haricot de lecteur de message (ou client de messages, cache-cache) qui sera enregistré dans un canal de messagerie ou une file d'attente de messages et activera sur la méthode de la poussée.

Votre producteur de messages crée un message et tous les autres serveurs clients enregistrés (consommateurs) en seront informés et le traiteront de manière asynchrone. Vous pouvez utiliser n'importe quelle plate-forme et open source Apache MQ. https://fr.wikipedia.org/wiki/Message_Queue


0 commentaires