개발 공부 로그

[Java] 네트워크 예외 - 연결 예외, 타임아웃 본문

카테고리 없음

[Java] 네트워크 예외 - 연결 예외, 타임아웃

mejii 2025. 5. 28. 10:50

 

✔️ java.net.UnknownHostException

- 호스트를 알 수 없음(IP 존재X, 도메인 이름 존재X)

✔️ java.net.ConnectException: Connection refused

- 네트워크를 통해 해당 IP의 서버 컴퓨터에 접속은 했음

- IP에 해당하는 서버는 켜져있지만, 사용하는 Port가 없을 때 주로 발생

- 네트워크 방화벽 등에서 무단 연결로 인지하고 연결을 막을 때도 발생

- 서버 컴퓨터의 OS는 이때 TCP RST(Reset) 라는 패킷을 보내서 연결을 거절

- 클라이언트가 연결 시도 중에 RST 패킷을 받으면 이 예외 발생

 

✔️ 타임아웃(연결 타임아웃)

public class ConnectTimeoutMain1 {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();

        try{
            Socket socket = new Socket("192.168.1.250",45678);
        }catch (ConnectException e){
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("Time taken : "+(end-start)+"ms");

    }
}

 

 주로 공유기에서 사용하는 IP 대역 "192.168.1.250" 을 사용했다. 해당 IP로 연결 패킷을 보내지만 IP를 사용하는 서버가 없으므로 TCP 응답이 오지 않는다. (대부분 공유기에는 서버가 없는 것으로 안다. ) 또는 해당 IP로 연결 패킷을 보내지만 해당 서버가 너무 바쁘거나 문제가 있어서 연결 응답 패킷을 보내지 못하는 경우도 있다. 이런 경우, 무한정 기다려야 할까? 
OS 마다 기본 TIMEOUT 대기 시간이 있고, 직접 설정할 수도 있다.

 

public class ConnectTimeoutMain2 {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();

        try{
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress("192.168.1.250",45678), 1000); //타임아웃 설정 1000ms
        }catch (SocketTimeoutException e){
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("Time taken : "+(end-start)+"ms");

    }
}

⭐️ TCP 소켓 타임아웃 - read 타임아웃

타임아웃 중에 또 하나의 중요한 타임아웃이 있다. 바로 소켓 타임아웃 또는 read 타임아웃이라고 부르는 타임아웃이다.

 앞의 연결 타임아웃은 TCP 연결과 관련있다. 이번에는 연결이 잘되었다고 하자.

연결이 잘 된 이후, 클라이언트가 서버에 어떤 요청을 했다. 그런데 서버가 계속 응답을 주지 않는다면, 무한정 기다려야 할까?

 서버에 사용자가 폭주해 매우 느려져서 응답을 계속 주지 못하는 상황에선 어떻게 해야할까?

 

Server

public class SoTimeoutServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        ServerSocket serverSocket = new ServerSocket(12345);
        Socket socket = serverSocket.accept();

        Thread.sleep(1000000000); // 계속 잠들어 있다
    }
}

 

Client

public class SoTimeoutClient {
    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("localhost", 12345);
        InputStream input = socket.getInputStream();

        try{
            socket.setSoTimeout(3000); //타임아웃 시간 설정
            int read = input.read();
            System.out.println("read = " + read);
        } catch (Exception e){
            e.printStackTrace();
        }

        socket.close();
    }
}

 

socket.setSoTimeout() 을 사용하면, 무한대기하지 않고 원하는 시간만큼만 대기할 수 있게 할 수 있다.

 

🧚🏼 외부 서버와 통신을 하는 경우 반드시 연결 타임아웃과 소켓 타임아웃(read 타임아웃) 설정하는 것을 잊지 말고 설정하자.


 

김영한 강사님의 실전 자바 고급 2편 강의와 강의자료를 참고해 작성된 글입니다.