Question

Je suis en train d'écrire un test client / serveur UDP et je souhaite le faire passer au travers du pare-feu. Soi-disant, tout ce que je dois faire, c'est que les deux côtés envoient à l'adresse IP et au serveur appropriés. Obtenir une adresse IP n'est pas un problème, mais comment puis-je demander au client de choisir un port libre aléatoire et de le signaler à l'utilisateur? Je souhaiterais éventuellement qu'il se connecte à un serveur de matchmaker, mais pour le moment, il me faut un prototype simple et fonctionnel, et j'aimerais connaître le numéro de port afin que mon ami / testeur puisse m'envoyer le # via messagerie instantanée afin que nous puissions tester.

Comment puis-je obtenir le numéro de port? désolé pour la longue desc. Je remarque que les gens me disent de ne pas faire ce que je demande quand je ne donne pas un desc: (

Était-ce utile?

La solution

Pour utiliser le terme hautement technique, il s’agit en fait d’un problème plutôt épineux, voire d’une paire de problèmes épineux. Selon la configuration du pare-feu, il autorisera généralement les réponses d'un autre point de terminaison sur le point de terminaison IP d'origine de la demande. Donc ... si votre ami reçoit le datagramme UDP en utilisant quelque chose comme l’appel système recvfrom () , le paramètre adresse recevra les informations de point de terminaison IP auxquelles répondre. Donc, l'autre extrémité devrait pouvoir répondre avec un sendto () en utilisant les mêmes informations d'adressage. Quelque chose comme:

/* initiator */
struct sockaddr_in hisaddr;
memset(&hisaddr, 0, sizeof(hisaddr));
hisaddr.sin_addr.s_addr = htonl(target_ip);
hisaddr.sin_port = htons(target_port);
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&hisaddr, sizeof(hisaddr));

/* receiver */
struct sockaddr_in peeraddr;
socklen_t peer_sz = sizeof(peeraddr);
recvfrom(sd, buf_ptr, buf_sz, 0, (struct sockaddr*)&peeraddr, &peer_sz);
/* build response */
sendto(sd, msg_ptr, msg_sz, 0, (struct sockaddr*)&peeraddr, peer_sz);

Le peeraddr de l'autre côté sera votre adresse externe ou, plus correctement, l'adresse IP de votre pare-feu et le numéro de port qu'il a choisi d'utiliser. Le numéro de port que vous spécifiez dans votre code peut être complètement différent de celui auquel votre ami devrait envoyer des données. En fin de compte, le port que vous choisirez d’importer n’importe peut-être pas puisque le pare-feu peut envoyer et recevoir sur un port entièrement différent - c’est ce que La traduction d'adresses réseau est tout au sujet. Je recommanderais de lire RFC3235 pour des conseils sur la manière de surmonter cet obstacle.

La meilleure approche à mon humble avis est de:

  1. Laissez le système d'exploitation choisir un port en appelant bind () avec un numéro de port égal à zéro ou ignorant complètement la liaison
  2. Demander au client de recevoir les informations d'adresse de la couche de socket (par exemple, les cinquième et sixième arguments de recvfrom () )
  3. Le client envoie une réponse au noeud final récupéré à l'étape précédente
  4. Modifiez les configurations du pare-feu jusqu'à ce que les étapes précédentes fonctionnent

Bien sûr, toute la magie est dans la dernière étape. Si vous pouvez désactiver la fonction NAT ou vous assurer que le pare-feu ne changera jamais de port, il vous suffira de cliquer sur un numéro de port et de lui donner bind pour qu'il fonctionne. Vous voudrez peut-être consulter % WINDIR% \ system32 \ drivers \ etc \ services (ou / etc / services en fonction de l'inclinaison de votre système d'exploitation) pour avoir une idée de quels numéros de port sont réservés ou généralement utilisés.

Autres conseils

De manière générale, en tant que développeur, choisissez le port. Vous pouvez configurer votre application pour qu'elle lise le port à partir d'un fichier de configuration ou d'une entrée utilisateur - mais aucun pare-feu magique ne vous dira quel port utiliser ...

Si je comprends bien votre question, je ne suis pas sûr qu'il y ait un moyen de faire ce que vous voulez par programmation (et même s'il y en a, je ne pense pas que ce soit la bonne approche). Je pense que vous devez rechercher un port qui n'est pas utilisé sur la machine serveur (et peut-être un port différent ou identique sur la machine client, si la communication est bidirectionnelle) ET ce port doit pouvoir passer à travers votre pare-feu. . Je suppose que puisque vous dites "obtenir une adresse IP n'est pas un problème", vous avez déjà configuré votre pare-feu pour transférer tout ou partie des ports vers un ordinateur spécifique à l'intérieur du pare-feu? Si tel est le cas, le port que vous recherchez fait partie de ceux que vous avez transférés. Vous pouvez simplement en choisir un, à condition qu'aucun autre service ne s'exécute sur ce port. Les ports inférieurs à 1024 sont réservés, vous voudrez donc probablement en choisir un nombre supérieur. Vous pouvez utiliser un simple outil d'analyse de port tel que nmap pour voir quels services sont exécutés sur votre ordinateur sur quels ports et en choisir un autre. un. Notez que nmap peut être trompé par des pare-feu et diverses règles bind lors de la création de sockets.

Je pense que vous feriez mieux de choisir un port fixe plutôt que de vous fier au numéro de port aléatoire choisi par le système d'exploitation.

Si vous utilisez un port aléatoire, vous devrez modifier les paramètres de votre pare-feu à chaque fois que vous exécutez le programme.

Si vous utilisez WINSOCK, vérifiez ce lien: http://msdn.microsoft.com/en-us /library/aa280717(VS.60).aspx En gros, vous avez 2 choix: définissez le port sur 0 et laissez le système vous en attribue un ou choisissez-en un aléatoire. Essayez d’ouvrir le socket s’il ne fonctionne pas, essayez-en un autre (veillez à éviter les ports réservés).

bind () le socket avant d'envoyer vos données. Spécifiez le port 0 à bind (), et le système d'exploitation choisira un port inutilisé pour vous. Vous pouvez ensuite utiliser getsockname () pour savoir quel port wsa a été choisi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top