localhost에서 사용 가능한 포트 번호를 어떻게 선택합니까?


166

프로세스 간 통신을 시도하고 있는데 Windows에서 명명 된 파이프를 사용하는 방법을 알 수 없었기 때문에 네트워크 소켓을 사용할 것이라고 생각했습니다. 모든 것이 로컬에서 발생합니다. 서버는 별도의 프로세스에서 슬레이브를 시작할 수 있으며 일부 포트에서 수신 대기합니다. 노예들은 일을하고 그 결과를 주인에게 제출합니다. 사용 가능한 포트를 어떻게 알 수 있습니까? 포트 80이나 21에서들을 수 없다고 생각합니까?

선택 사항이 줄어들면 Python을 사용하고 있습니다.

감사!


1
덧붙여서, 임의의 또는 임의의 포트 번호 (가급적이면 1024보다 높은 번호)를 선택하면 아마도 사용할 수있을 것입니다. 다른 프로그램이 수신하지 않는 한 포트 80이나 21 등을 사용할 수도 있습니다. 주어진 시간에 일반 시스템에서는 포트의 일부만 사용됩니다.
David Z

19
임의의 포트를 선택하는 것은 좋은 생각이 아닙니다. OS가 선택하도록하십시오.
Corehpf

답변:


232

특정 포트에 바인딩하거나 포트 0에 바인딩하지 마십시오 sock.bind(('', 0)). 그러면 OS가 사용 가능한 포트를 선택합니다. 를 사용하여 선택한 포트를 가져 와서 sock.getsockname()[1]다시 연결할 수 있도록 슬레이브에 전달할 수 있습니다.


4
예를 보려면 stackoverflow.com/a/2838309/3538289 를 참조하십시오.sock.bind(('',0))
cevaris

12
번호를 노예에게 어떻게 전달합니까? 나에게 닭고기와 달걀 문제처럼 들린다.
세바스찬

2
바인딩 후 슬레이브가 생성되면 생성시 매개 변수로 전달하면됩니다. 또는 공유 메모리 나 둘 다 액세스 할 수있는 파일에 기록하거나 잘 알려진 포트 번호를 통해 액세스 한 중앙 서버가이를 추적 할 수 있습니다.
mark4o

55

위에서 설명한 내용의 일부를 위해 :

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]

3
localhost의 경우 : 어쩌면 s.bind(('localhost', 0))
codeskyblue는

4
또한 다음을 추가하여 반환 진술 전에 해당 포트를 신속하게 재사용 할 수 있습니다.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
jonEbird

1
@jonEbird socket.SO_REUSEADDR이 경우 정말 도움이 되나요? 내가 읽은 바인드하려는 소켓이 있다는 것만 관련이 있으며 SO_REUSEADDR그 플래그가 느린 소켓에 설정되어 있는지 여부는 관련이 없습니다.
Karl Bartel

41

소켓을 포트 0에 바인딩합니다. 1024에서 65535 사이의 임의의 사용 가능한 포트가 선택됩니다. getsockname()바로 뒤에 선택한 포트를 검색 할 수 있습니다 bind().


2

원하는 포트에서들을 수 있습니다. 일반적으로 사용자 응용 프로그램은 포트 1024 이상 (65535를 통해)을 수신해야합니다. 리스너 수가 가변적 인 경우 가장 중요한 것은 앱에 범위 (예 : 20000-21000 및 CATCH EXCEPTIONS )를 할당하는 것 입니다. 이것이 컴퓨터에서 포트를 사용할 수 없는지 (다른 프로세스에 의해 사용됨) 알 수있는 방법입니다.

그러나 귀하의 경우에는 바인딩이 실패 할 경우 오류 메시지를 인쇄하는 한 리스너에 대해 단일 하드 코딩 된 포트를 사용하는 데 문제가 없어야합니다.

또한 대부분의 소켓 (슬레이브 용)은 특정 포트 번호에 명시 적으로 바인딩 할 필요가 없습니다. 들어오는 연결을 기다리는 소켓 (예 : 여기서 마스터) 만 리스너로 만들어 포트에 바인딩해야합니다. 포트가 사용되기 전에 소켓에 ​​대해 지정되지 않은 경우 OS는 사용 가능한 포트를 소켓에 할당합니다. 마스터가 데이터를 전송하는 슬레이브에 응답하고자 할 때 리스너가 데이터를 수신 할 때 발신자의 주소에 액세스 할 수 있습니다.

나는 당신이 이것을 위해 UDP를 사용할 것이라고 생각합니까?


1

나중에 사용하기 위해 사용 가능한 포트만 찾아야하는 경우 이전 답변 과 비슷 하지만 socketserver를 사용하는 더 짧은 스 니펫이 있습니다 .

import socketserver

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

포트가 무료로 유지된다는 보장은 없으므로이 스 니펫과이를 사용하는 코드를 루프에 넣어야 할 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.