HOWTO · Python
ConnectionRefusedError: [Errno 111] Connection Refused 해결 방법
이 기사에서는 ConnectionRefusedError가 무엇인지 알아봅니다. 이 오류는 기본적으로 클라이언트가 서버 스크립트를 실행하는 시스템의 포트에 연결할 수 없음을 나타냅니다.
이 페이지의 내용
ConnectionRefusedError: [Errno 111] Connection refused는 TCP 연결 시도가 대상에 의해 거부되었음을 의미합니다. 일반적으로 해당 주소와 포트에서 연결을 수락하는 서비스가 없기 때문입니다. ping이 성공했다는 것은 호스트가 네트워크 프로브에 응답할 수 있다는 것을 보여줄 뿐, 특정 TCP 서비스가 수신 대기 중임을 확인해 주지는 않습니다.
Python에서 ConnectionRefusedError: [Errno 111] Connection refused가 발생하는 이유
요청한 TCP 엔드포인트가 연결을 거부하면 운영 체제가 Python에 거부를 보고합니다. 먼저 서버 프로세스가 실행 중이며 수신 대기 중인지 확인하세요. 그런 다음 클라이언트가 사용하는 정확한 주소와 포트를 서버의 수신 대기 주소 및 포트와 비교하세요. 127.0.0.1에만 바인딩된 서버는 자신의 컴퓨터에서 온 연결만 수락하고 다른 컴퓨터의 연결은 수락하지 않습니다. 방화벽도 연결을 거부할 수 있습니다.
이는 TCP 연결을 시도하기도 전에 발생하는 호스트 이름 조회 실패와는 다릅니다. 시간 초과나 라우팅 실패는 대개 클라이언트가 거부 응답을 받지 못했음을 의미합니다. 잘못된 주소는 네트워크에 따라 다른 결과를 초래할 수 있으며, 그 자체만으로 이 오류를 보장하지는 않습니다.
거부된 Python 소켓 연결 진단 및 수정
먼저 서버를 확인한 다음, 양쪽에서 대상 주소와 포트를 검증하세요. 서버가 수신 대기하는 인터페이스를 확인하세요. 같은 컴퓨터의 클라이언트에는 루프백을, 다른 호스트에는 의도한 네트워크 인터페이스를 사용하세요. 0.0.0.0에 바인딩하면 모든 IPv4 인터페이스에서 수신 대기하므로 서비스가 다른 컴퓨터에 노출될 수 있습니다. 따라서 설정에 맞는 가장 좁은 인터페이스를 선택하세요. 서비스가 예상 엔드포인트에서 수신 대기 중이라면 방화벽 규칙을 검토하세요.
이 독립 실행형 예제는 백그라운드 스레드에서 로컬 서버를 시작하고, 같은 루프백 포트로 클라이언트를 연결한 뒤, 바이트 문자열을 전송합니다. 포트는 운영 체제가 할당하므로 두 소켓이 별도의 파일이나 셸 명령 없이 같은 엔드포인트를 사용합니다. 클라이언트는 알려진 응답 길이를 받을 때까지 읽습니다. 서버가 그보다 먼저 연결을 닫으면, 부분적인 데이터를 완전한 메시지인 것처럼 제시하지 않고 응답이 불완전했음을 알립니다.
import socket
import threading
with socket.socket() as server:
server.bind(("127.0.0.1", 0))
server.listen()
port = server.getsockname()[1]
def serve():
connection, _ = server.accept()
with connection:
connection.recv(1024)
connection.sendall(b"hello from server")
worker = threading.Thread(target=serve)
worker.start()
with socket.create_connection(("127.0.0.1", port)) as client:
client.sendall(b"hello from client")
response_length = len(b"hello from server")
response = bytearray()
complete = True
while len(response) < response_length:
chunk = client.recv(response_length - len(response))
if not chunk:
complete = False
break
response.extend(chunk)
if complete:
print(response.decode())
else:
print("Server closed before the full response arrived")
worker.join()
두 개의 별도 프로그램을 사용하는 경우, 클라이언트보다 먼저 서버를 시작하고, 서버 프로세스가 accept()에서 대기하는 동안 계속 실행되게 하세요. 두 프로그램에 같은 포트를 설정하고, 클라이언트가 자신의 컴퓨터에서 도달할 수 있는 주소로 연결하게 하세요. 127.0.0.1은 두 프로그램이 같은 호스트에서 실행될 때만 사용하세요. 원격 클라이언트라면 서버 컴퓨터의 도달 가능한 인터페이스 주소를 사용하고 접근을 신중하게 구성하세요. 위 예제는 성공적인 교환을 단일 프로세스로 보여주는 데모이며, 외부 공개용 리스너를 구성하지는 않습니다.
호스트 이름만 실패한다면 이름 확인을 별도로 조사하세요. socket.gethostbyname("example.com")은 IPv4 주소를 조회할 뿐, 서비스를 시작하거나 거부된 연결을 복구하지 않습니다. 호스트 이름이 확인되면, 반환된 주소가 서버가 수신 대기 중인 주소인지, 그리고 클라이언트가 서버의 포트를 사용하는지 확인하세요.
결론
ConnectionRefusedError는 거부된 TCP 연결을 가리킵니다. 서버가 실행 중이고, 의도한 인터페이스에서 수신 대기 중이며, 클라이언트가 대상으로 하는 것과 같은 주소와 포트를 사용하는지 확인하세요. 그런 다음 방화벽 규칙을 검토하고, 호스트 이름 확인은 별도의 진단으로 취급하세요.