Pouvez-vous bind() et connect (), les deux extrémités d'une connexion UDP
Je suis en train d'écrire un point à un message de la file d'attente du système, et il doit être capable de fonctionner sur UDP. Je peut arbitrairement choisir un côté ou de l'autre pour être le "serveur" mais il ne semble pas tout à fait la droite depuis les deux extrémités sont en envoyant et recevant le même type de données de l'autre.
Est-il possible de bind() et connect (), les deux extrémités de manière à ce qu'ils envoient/reçoivent seulement les uns des autres? Qui semble que bien symétrique façon de le faire.
- Semble un peu étrange, mais je ne vois pas pourquoi pas.
connect()
juste définit la valeur par défaut adresse de destination/port pour le socket. (Avez-vous essayé? Si cela ne fonctionne pas pour une raison quelconque, il suffit d'utilisersendto()
.) Personnellement je venais d'utilisersendto()
parce que sinon, vous allez obtenir confus si plusieurs clients de se connecter à votre serveur.
Vous devez vous connecter pour publier un commentaire.
UDP sans connexion, donc il n'y a que peu de sens pour l'OS en fait une sorte de connexion.
Dans sockets BSD, on peut faire une
connect
sur un socket UDP, mais c'est fondamentalement juste définit la valeur par défaut adresse de destination poursend
(au lieu de donner explicitement àsend_to
).Lier sur un socket UDP indique au système d'exploitation pour lequel entrant adresse à accepter des paquets (tous les paquets à d'autres adresses sont supprimés), quel que soit le type de socket.
Lors de la réception, vous devez utiliser
recvfrom
pour identifier la source du paquet provient d'. Notez que si vous voulez une sorte d'authentification, puis en utilisant simplement les adresses concernées est aussi incertain que pas de serrure à tous. Les connexions TCP peut être détourné et nu UDP a littéralement usurpation d'adresse IP écrit sur sa tête. Vous devez ajouter une sorte de HMACrecvfrom
sur un socket UDP sur lequelbind()
a été appelé, et il continue d'accepter les paquets depuis des adresses arbitraires.Bonjour de l'avenir lointain, qui est l'année 2018, pour l'année 2012.
Il y a, en fait, une raison derrière
connect()
ing un socket UDP dans la pratique (même si béni POSIX n'est pas, en théorie, vous demandent de vous).Ordinaire socket UDP ne sait rien au sujet de ses futures destinations, ainsi il effectue une recherche d'itinéraire à chaque fois
sendmsg()
est appelé.Toutefois, si
connect()
est appelé à l'avance avec une certaine distance du récepteur IP et le port, le noyau du système d'exploitation sera en mesure de écrivez la référence à l'itinéraire et à l'attribuer à la prise, le rendant beaucoup plus rapide pour envoyer un message si, à la suitesendmsg()
appels ne spécifiez pas un récepteur (sinon, le réglage précédent sera ignoré), le choix de la valeur par défaut à la place.Regarder la les lignes de
1070
par1171
:Jusqu'à ce que le noyau Linux 4.18, cette fonctionnalité a été principalement limité à l'adresse IPv4 de la famille seulement. Cependant, depuis 4.18-rc4 (et, espérons-le noyau Linux version 4.18 ainsi), il est entièrement fonctionnel avec IPv6 ainsi.
Elle peut être une source de un sérieux avantage en matière de performances, mais il dépendra fortement de l'OS que vous utilisez. Au moins, si vous êtes sous Linux et n'utilisez pas la prise de distance multiples gestionnaires, vous devez lui donner un essai.
Voici un programme qui montre comment bind() et connect() sur le même socket UDP à un ensemble spécifique de ports source et destination, respectivement. Le programme peut être compilé sur toute machine Linux et a l'utilisation suivante:
J'ai testé ce code d'ouverture de deux terminaux. Vous devriez être en mesure d'envoyer un message vers le nœud de destination et de recevoir des messages à partir de ce.
Dans le terminal 1 exécuter
Dans le terminal 2 exécutez
Même si je l'ai testé sur une seule machine, je pense qu'il devrait également travailler sur deux machines différentes, une fois que vous avez configuré l'corriger les paramètres du pare-feu
Voici une description du flux:
Vraiment la clé est
connect()
:connect
ed sockets sont liés de toute façon. de connecter l'homme page:If the socket has not already been bound to a local address, connect() shall bind it to an address which, unless the socket's address family is AF_UNIX, is an unused local address.
Cette page contient quelques info sur connecté rapport de connexité sockets:
http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch08lev1sec11.html
Cette citation répond à votre question:
Je n'ai pas utilisé connect() en vertu de l'UDP. Je me sens connect() a été conçu pour deux totalement différentes fins selon vs UDP TCP.
La page de man a quelques brefs détails sur l'utilisation de connect() en vertu de l'UDP:
Il y a un problème dans votre code:
En utilisant AF_UNSPEC et SOCK_DGRAM seulement, vous permet d'obtenir une liste de tous les possibles addrs. Ainsi, lorsque vous appelez socket, l'adresse que vous utilisez peut-être pas prévu, UDP un. Vous devez utiliser
au lieu de assurez-vous que le addrinfo vous obtenez est ce que vous vouliez.
En un mot, la prise que vous avez créé ne peut pas être une socket UDP, et c'est la raison pourquoi il ne fonctionne pas.
OUI, vous le pouvez. Je le fais aussi.
Et votre cas est celui où c'est utile: à la fois côté agissent à la fois comme client & serveur, et il n'y a qu'un seul processus à la fois côté.
Je le regarde plus de l'idée de ce que UDP est à fournir. UDP est de 8 octets d'en-tête qui ajoute 2 octets d'envoyer et de recevoir des ports (4 octets au total). Ces ports interagir avec les Sockets Berkeley pour offrir à votre traditionnel socket interface. I. e. vous ne pouvez pas lier à une adresse sans un port ou vice-versa.
Généralement lorsque vous envoyez un paquet UDP de le recevoir côté port (source) est éphémère et le côté de l'envoi (port de destination) est votre port de destination sur l'ordinateur distant. Vous pouvez désactiver ce comportement par défaut en se liant d'abord et ensuite la connexion. Maintenant, votre port source et port destination serait la même aussi longtemps que les mêmes ports sont gratuits sur les deux ordinateurs.
En général, ce comportement (appelons-le port de détournement), c'est mal vu. C'est parce que vous avez juste limité envoyer votre côté à seulement capable de l'envoyer d'un processus, plutôt que de travailler au sein de l'éphémère modèle qui alloue dynamiquement envoyer du côté de la source de ports.
D'ailleurs, les quatre autres octets de huit octets UDP charge utile, de la longueur et de la CRC sont à peu près totalement inutile comme ils sont déjà fournis dans le paquet IP et UDP en-tête est de longueur fixe. Comme viennent sur les personnes, les ordinateurs sont assez bon à faire un peu de soustraction.
Si vous êtes en c/c++ amant, vous pouvez essayer route_io
Il est simple à utiliser, créer une instance d'accepter de port différent de routage à votre fonction.
Exemple :