178 votes

Sur localhost, comment choisir un numéro de port libre ?

J'essaie de jouer avec la communication inter-processus et comme je n'ai pas réussi à comprendre comment utiliser les named pipes sous Windows, j'ai pensé utiliser les sockets réseau. Tout se passe localement. Le serveur est capable de lancer des esclaves dans un processus séparé et écoute sur un port. Les esclaves font leur travail et soumettent le résultat au maître. Comment puis-je savoir quel port est disponible ? Je suppose que je ne peux pas écouter sur le port 80 ou 21 ?

J'utilise Python, si cela réduit les choix.

1 votes

Par ailleurs, si vous choisissez un numéro de port aléatoire ou proche du hasard (de préférence supérieur à 1024), il sera probablement disponible. Vous pouvez même utiliser le port 80, 21 ou autre, tant qu'aucun autre programme ne l'écoute. À tout moment, sur un système normal, seule une petite fraction des ports est utilisée.

24 votes

Choisir un port au hasard n'est pas une bonne idée - laissez le système d'exploitation en choisir un pour vous.

0 votes

248voto

mark4o Points 20472

Ne pas se lier à un port spécifique. Au lieu de cela, liez vous au port 0 :

sock.bind(('', 0))

Le système d'exploitation choisira alors un port disponible pour vous. Vous pouvez obtenir le port qui a été choisi en utilisant sock.getsockname()[1] et le transmet aux esclaves pour qu'ils puissent se connecter en retour.

sock est le socket que vous avez créé, renvoyé par socket.socket .

5 votes

Voir stackoverflow.com/a/2838309/3538289 pour un exemple de sock.bind(('',0))

13 votes

Comment transmettre le numéro aux esclaves ? Ça ressemble à un problème de poule et d'oeuf pour moi.

2 votes

Si les esclaves sont créés après la liaison, vous pouvez simplement le passer comme paramètre lors de leur création. Vous pouvez également l'écrire dans une mémoire partagée ou un fichier auquel les deux parties peuvent accéder, ou un serveur central auquel on accède via un numéro de port bien connu pourrait en garder la trace.

71voto

saaj Points 412

Pour le bien de la bribe de ce que les gars ont expliqué ci-dessus :

import socket
from contextlib import closing

def find_free_port():
    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
        s.bind(('', 0))
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        return s.getsockname()[1]

44voto

Havenard Points 9023

Lier la socket au port 0. Un port libre aléatoire compris entre 1024 et 65535 sera sélectionné. Vous pouvez récupérer le port sélectionné avec getsockname() juste après bind() .

3voto

Walt W Points 2074

Vous pouvez écouter sur le port de votre choix ; en général, les applications utilisateur doivent écouter sur les ports 1024 et plus (jusqu'à 65535). Si vous avez un nombre variable d'auditeurs, l'essentiel est d'attribuer une plage à votre application - disons 20000-21000, et ATTRAPE LES EXCEPTIONS . C'est ainsi que vous saurez si un port est inutilisable (utilisé par un autre processus, en d'autres termes) sur votre ordinateur.

Cependant, dans votre cas, vous ne devriez pas avoir de problème à utiliser un seul port codé en dur pour votre écouteur, tant que vous imprimez un message d'erreur si la liaison échoue.

Notez également que la plupart de vos sockets (pour les esclaves) n'ont pas besoin d'être explicitement liées à des numéros de port spécifiques - seules les sockets qui attendent des connexions entrantes (comme votre maître ici) devront être transformées en auditeur et liées à un port. Si un port n'est pas spécifié pour une socket avant qu'elle ne soit utilisée, le système d'exploitation assignera un port utilisable à la socket. Lorsque le maître veut répondre à un esclave qui lui envoie des données, l'adresse de l'expéditeur est accessible lorsque le listener reçoit des données.

Je suppose que vous utiliserez UDP pour cela ?

2voto

Mihai Capotă Points 140

Si vous avez seulement besoin de trouver un port libre pour une utilisation ultérieure, voici un extrait similaire à une réponse précédente mais plus court, en utilisant socketserver :

import socketserver

with socketserver.TCPServer(("localhost", 0), None) as s:
    free_port = s.server_address[1]

Notez que le port n'est pas garanti de rester libre, donc vous pouvez avoir besoin de mettre ce snippet et le code l'utilisant dans une boucle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X