Java 소켓: 타임아웃 설정 및 재시도 방법

코드 예제: Java Socket에서 타임아웃과 재시도 로직을 통한 안정적인 요청/응답 구현

1. 소켓 설정 및 타임아웃 적용

Java의 Socket 클래스에는 연결 타임아웃과 리드 타임아웃을 설정할 수 있습니다. 연결 타임아웃을 설정하여 서버 응답 지연 시 자동으로 연결을 해제하고, 재시도 로직을 통해 일정 횟수까지 다시 연결을 시도할 수 있습니다.

import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class SocketClient {

    private final String host;
    private final int port;
    private final int maxRetries = 3; // 최대 재시도 횟수
    private final int connectionTimeout = 5000; // 연결 타임아웃 (5초)
    private final int readTimeout = 5000;       // 리드 타임아웃 (5초)

    public SocketClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public String sendRequest(String message) {
        int retries = 0;

        while (retries < maxRetries) {
            try (Socket socket = new Socket()) {
                // 소켓 타임아웃 설정
                socket.connect(new java.net.InetSocketAddress(host, port), connectionTimeout);
                socket.setSoTimeout(readTimeout);

                // 요청 데이터 전송
                OutputStream output = socket.getOutputStream();
                PrintWriter writer = new PrintWriter(output, true);
                writer.println(message);

                // 응답 데이터 수신
                InputStream input = socket.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(input));
                return reader.readLine(); // 응답 메시지 반환

            } catch (SocketTimeoutException e) {
                System.out.println("Timeout occurred. Retrying... (" + (retries + 1) + "/" + maxRetries + ")");
                retries++;
            } catch (IOException e) {
                System.out.println("Connection error: " + e.getMessage());
                retries++;
            }

            // 재시도 전 대기 (1초)
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Thread interrupted during retry delay", ie);
            }
        }

        // 최대 재시도 횟수를 초과할 경우 기본 응답 반환
        return "Service unavailable after multiple retries";
    }

    public static void main(String[] args) {
        SocketClient client = new SocketClient("localhost", 8080);
        String response = client.sendRequest("Hello, Server!");
        System.out.println("Server response: " + response);
    }
}

코드 설명

  • 타임아웃 설정: socket.connect(new java.net.InetSocketAddress(host, port), connectionTimeout)에서 연결 타임아웃을 설정하며, socket.setSoTimeout(readTimeout)으로 데이터 수신 시의 타임아웃을 설정합니다. 타임아웃이 초과되면 SocketTimeoutException이 발생합니다.
  • 재시도 로직: 요청 실패 시 maxRetries까지 재시도하며, 실패할 때마다 1초 대기합니다. 네트워크 불안정 상태에서 재시도하여 정상 응답을 받을 가능성을 높입니다.
  • 방어 로직: 재시도 횟수를 초과하거나 연결 오류가 발생할 경우 "Service unavailable after multiple retries"라는 기본 응답을 반환합니다.

이 코드를 통한 안정적인 소켓 요청/응답의 장점

이 소켓 클라이언트는 서버 연결 시 응답을 기다리면서 발생할 수 있는 지연 문제에 대해 타임아웃과 재시도 로직을 통해 안정성을 보장합니다. 이 구조는 실시간 통신 환경에서도 네트워크 부하에 대응할 수 있도록 설계되어, 클라이언트와 서버 간의 지속적인 통신을 유지하는 데 매우 유용합니다.

위로 스크롤