2009-06-04 12 views
8

Załóżmy, że chcę uruchomić usługę TCP/IP na pewnym porcie dla IPC. Podczas przesyłania numeru portu do procesów, z którymi chcę się komunikować, numer portu nie ma znaczenia. Jaki jest najlepszy sposób uzyskania losowego, wysokiego (zwykle> 49152) numeru portu, który jest nadal dostępny w systemie? Czy jest coś w POSIXu, którego mogę użyć?Uzyskaj losowy, wysoki numer portu, który jest nadal dostępny

Wiem, że serwery FTP potrzebują tego często.

Odpowiedz

-9

Jedynym sposobem jest przeplot przez żądany zakres portów, próbując połączyć gniazdo z każdym portem po jednym na raz, dopóki nie znajdziesz takiego, które się powiedzie.

+2

Nie, to nie jest to jedyny sposób. Wiązanie z portem zerowym to inny sposób i nieskończenie lepszy sposób. QED – EJP

13

Jeśli nie podasz numeru portu, system automatycznie wybierze numer ephemeral port.

Od Choosing the Port Number:

Nowe oprogramowanie serwera powinien starać się unikać w zależności od konkretnego numeru portu, zwłaszcza jeśli jest to oprogramowanie na poziomie użytkownika, który nie jest nierozerwalnie związany z dobrze znanego portu. Na szczęście łatwo to zrobić, żądając portu 0, który nakazuje systemowi wybrać efemeryczny numer portu.

+1

Tak, port 0 pozwala systemowi wybrać losowy dostępny port. Z drugiej strony korzystanie z portu 0 nie pozwala określić zakresu portów, z których system operacyjny może wybrać. Jeśli na przykład znajdujesz się za zaporą/routerem, ważniejsze staje się korzystanie z zakresów portów. –

+1

@RemyLebeau Każda zapora, która jest skonfigurowana tak, aby zezwalać tylko na zakres portów wychodzących, jest źle skonfigurowana i powinna zostać naprawiona. Ponieważ interfejs API Socket tego nie obsługuje, obciąża on aplikacje, których nie może spełnić, a także jest całkowicie bezsensowny z punktu widzenia bezpieczeństwa. – EJP

+0

@EJP: Zakładasz, że powiązanie portów jest wykonywane tylko dla * połączeń wychodzących *. Protokół FTP jest dobrym przykładem tego, kiedy klient może potrzebować wiązać gniazda dla * połączeń przychodzących * dla transferów w trybie aktywnym. –

5

Efemeryczne porty mogą to zrobić. Twój system operacyjny przydzieli ci port z bezpłatnej puli portów.

Istnieją pewne kod C, BSD-licencjonowany, robi to here

w Pythonie, można określić ('', 0) socket.AF_INET parę adresów w tym samym celu, na przykład sock.bind(('', 0))

+0

Jakiej funkcji Python powinniśmy wywoływać z argumentami ('127.0.0.1', 0)? –

+1

@ Nordlöw - [bind] (http://docs.python.org/2/library/socket.html#socket.socket.bind) –

+0

To jest odpowiedź python: http://bit.ly/1o9GlOY – yucer

0

Można używać mojego małego C Library: https://github.com/yegor256/random-tcp-port

skompilować i uruchomić na komputerze. Wyprowadzi losowy port TCP dostępny.

+3

Która natychmiast stanie się dostępny dla kogoś innego zaraz po jego wyjściu. Jest to całkowicie bezcelowe. – EJP

+0

Ale to jest dokładnie to, co zasugerowałeś kilka odpowiedzi poniżej, a wszystkie inne odpowiedzi również sugerują :) Moja biblioteka po prostu ułatwia uzyskanie – yegor256

+1

Robisz to źle. Przypisywanie losowych portów jest już częścią systemu - wszystko, co musisz zrobić, to zażądać numeru portu 0, a otrzymasz losowy port, który możesz uzyskać za pomocą 'getsockname'. Jeśli jednak zamkniesz gniazdo, nie masz gwarancji, że ten stary, efemerydalny numer portu będzie nadal dostępny. – PSkocik

1

Jeśli spróbujesz połączyć się z numerem portu 0, system połączy twoje gniazdo z losowym portem "efemeryd". Następnie można uzyskać port z getsockname (w C).

W Ruby:

s = TCPServer.new('localhost', 0) #You can also use nil instead of 0 
s.addr[1] #The obtained port number 
+0

Ephemereal? Jak długo to potrwa? Mam nadzieję, że dopóki serwer się nie zatrzyma. – yucer

+0

@yucer Oznacza to, że nie jest to ustalona liczba związana z konkretną usługą stałą, taką jak 80 dla HTTP. To będzie trwało dopóki nie zamkniesz lub dopóki system operacyjny nie zamknie go, gdy twój proces się zakończy. – PSkocik

+0

Myślę, że konstruktor się zmienił. Zobacz: http://bit.ly/1o9DDJb Również atrybutem addr jest teraz adres_serwera – yucer