Programming/Java

FTP로 살펴보는 SocketTimeout(soTimeout)과 ConnectionTimeout 차이점

Jan92 2023. 2. 1. 22:28

FTPClient connect() method

FTPClient로 살펴보는 SocketTimeout, ConnectionTimeout 차이점

Java FTPClient를 통한 ftp 파일 업로드를 구현하는 과정에서 FTPClient에 기본적으로 ConnectionTimeout이 설정되어 있는 상태에서 setSoTimeout() 메서드를 통해 socketTimeout이 설정되는 것을 보고 'SocketTimeout과 ConnectionTimeout의 차이점'에 대한 의문이 생겨서 정리한 내용입니다.

 


ConnectionTimeout

connection timeout

FTP(File Transfer Protocol)는 TCP/IP를 기반으로 한 파일 전송 프로토콜로 ftp server에 파일 업로드(다운로드, 삭제 등)를 하기 위해서는 ftp server와 연결된 상태가 되어야 합니다.

 

FTPClient는 connect() 메서드를 통해 서버와의 연결을 요청하며 3-way Handshake 방식으로 연결을 수행하게 되는데요.

3-way Handshake 과정이 정상적으로 수행되면 ftp client와 ftp server는 연결 상태가 됩니다.

이 과정에서 소요된 시간을 connection에 소요된 시간으로 볼 수 있는데, connectionTimeout은 connection을 구성하는 데 소요되는 시간의 임계치를 의미합니다.

 

// 임계치: 어떤 현상이 갈라져서 다르게 나타나기 시작하는 경계의 값, 기준이 되는 값

 

 

super.connect(epoint, remainingMillis(deadlineMillis));

ftpclient에서 connectiontimeout이 발생하는 곳을 찾기 위해 코드를 따라가 보면, 구현체인 SocksSocketImpl 클래스에서 위 메서드가 실행되는 것을 볼 수 있습니다.

 

    final long deadlineMillis;

    if (timeout == 0) {
        deadlineMillis = 0L;
    } else {
        long finish = System.currentTimeMillis() + timeout;
        deadlineMillis = finish < 0 ? Long.MAX_VALUE : finish;
    }

deadlineMillis 값은 다음과 같이 정해지고 있는데요.

remainingMillis() 메서드는 아래와 같으며, remainingMillis() 메서드 내부에서 설정된 timeout 시간을 비교하여 SocketTimeoutException을 발생시키는 구조로 되어있습니다.

 

remainingMillis() method

(connection 역시 socket을 기반으로 이루어지기 때문에 SocketTimeoutException이 발생하는 것으로 생각됩니다.)

 

FTPClient는 connection() 메서드 호출 시 인증 및 명령어 입력을 위한 제어 채널 연결(Command Line Connection)이 구성되고 파일 업로드, 다운로드 등의 메서드(storeFile, retrieveFile)를 호출할 때 파일 전송 채널 연결(Data Line Connection)이 구성되는데요.

ConnectionTimeout은 각각의 연결에 따로 적용됩니다.

 


SocketTimeout

socket timeout

ftp client가 ftp server와 연결된 이후 ftp client는 서버로 데이터를 전송하거나, 서버로부터 데이터를 받을 수 있습니다.

이때 하나의 파일은 여러 개의 패킷으로 나눠서 전송되는데요. 각각의 패킷이 전송될 때, 패킷 전송 사이에 시간이 생길 수 있으며, 이 시간의 임계치를 SocketTimeout이라고 합니다.

 

SocketTimeout은 패킷 전체에 대한 응답을 수신하는 시간이 초과된 것을 의미하는 것이 아니라, 각각의 패킷 전송이 수신되는 시간에 대한 timeout이라는 점은 잘 알아두어야 하는 부분입니다.

(두 개의 연속 데이터 패킷 사이의 최대 비활성화 시간)

 

/*

패킷 교환(Packet Switching) 방식은 데이터를 패킷이라는 작은 단위로 나누어 다중 노드로 구성된 네트워크를 통해 전송하는 개념인데요. 데이터는 네트워크를 통해 전송되기 전에 패킷으로 나누어지고, 각 패킷에는 고유 번호가 지정되어 있어 네트워크를 거쳐 최종 수신지에 도착했을 때는 번호 순서대로 결합되어 원래 데이터로 완성되는 방식입니다.

*/

 

 

FTPClient byteTransferred() method

SocketTimeout 역시 발생하는 곳을 확인하기 위해 코드를 살펴보면, Util 클래스의 copyStream() 메서드에서 CopyStreamListener 객체의 인스턴스를 통한 bytesTransferred() 메서드가 실행되는 부분을 참고할 수 있는데요.

bytesTransferred() 메서드가 실제 구현된 부분은 FTPClient 클래스 내부 static class인 CSL에서 살펴볼 수 있습니다.

 

해당 메서드는 try-catch 부분을 통해 __noop() 메서드 실행 과정에서 발생하는 SocketTimeoutException을 잡아서 notAcked++ 로 처리하고 아래 cleanUp() 메서드를 통해 처리되었던 것 같은데, 현재 SocketTimeoutException이 발생했을 때 ignored 처리가 되어있어 NFT-584를 찾아보니 다음과 같은 이슈를 확인할 수 있었습니다.

 

https://issues.apache.org/jira/browse/NET-584

 

cleanUp() method

 

내용에 대해 궁금하신 부분이나 잘못된 부분이 있으면 댓글 남겨주시면 확인하여 수정하도록 하겠습니다. 미리 감사드립니다.

 

 

 

< 참고 자료 >

https://tomining.tistory.com/164

https://commons.apache.org/proper/commons-net/javadocs/api-3.6/org/apache/commons/net/ftp/FTPHTTPClient.html

https://velog.io/@haero_kim/물-흐르듯-읽어보는-TCPIP

 

 

< 관련 자료 >

2022.10.22 - [Programming/Web] - FTP Active Passive Mode 정리