요약
STRU R과MODE S조합에서 FTP는 데이터 스트림 안에 두 바이트짜리 제어 코드를 넣었다. 전부 1인 이스케이프 바이트 뒤에 1이 오면 레코드 끝(EOR), 2가 오면 파일 끝(EOF), 3이 오면 둘을 동시에 의미했다.- 리터럴 전체 1 데이터 바이트는 두 번 반복해야 했다. 따라서 수신 측은 두 배로 된 데이터와 구조적 경계를 구분하기 위해 협상된 맥락과 파서 상태가 필요했다.
- 이 설계는 이식 가능한 레코드 의미를 호스트 저장소 및 TCP 전달 조각과 분리했다. 이후 호스트 요구사항은 필수 레코드 지원 범위를 좁혔지만, 수용하는 경우에는 정직하고 가능하면 가역적인 처리를 여전히 요구했다.
하나로 해석되는 짝
수신자가 평범한 데이터를 모두 소비한 뒤 모든 비트가 1인 바이트를 마주쳤다고 상상해 보자. 이 시점에서는 그 바이트를 파일로 전달할 수 없다. 작은 상태 조각을 유지한 채 뒤따르는 바이트를 살펴봐야 한다.
다음 바이트 역시 전부 1이면 이 짝은 리터럴 데이터 바이트 하나를 나타낸다. 다음 값이 1이면 짝이 레코드를 닫는다. 값 2는 파일을 닫는다. 값 3은 같은 지점이 마지막 레코드 경계이자 파일의 끝이라고 말한다.
RFC 765와RFC 959에 보존된 이 간결한 문법은 모호한 리터럴 값을 남기지 않으면서 옥텟 하나가 두 가지 역할을 하게 했다. 첫 번째 전체 1 바이트 자체가 본질적으로 제어는 아니었다. 그 의미는 이웃한 바이트와, 제어 연결에서 이미 협상된 전송 파라미터가 완성했다.
두 배 규칙이야말로 가장 시사적인 세부 사항이다. 인밴드 센티널은 데이터 알파벳에서 하나의 값을 차지한다. 그 값을 파일에 돌려주기 위해 송신자는 같은 값을 한 벌 더 붙여 인용한다. 수신자는 그 연산을 되돌린다. 따라서 압축도 손실도 없었는데도 원시 전송 길이와 재구성된 데이터 길이가 달라질 수 있다.
스트림은 레코드 서비스가 아니었다
FTP는 구조와 전송 모드를 별개의 선택으로 기술했다.STRU F는 파일을 연속적인 데이터 바이트 열로 다뤘다.STRU R은 파일이 순차적인 레코드들로 이루어진다고 선언했다.MODE S는 전송을 위해 거의 프레임 없는 바이트 스트림을 선택했다.
이 조합이 중요했다. 스트림 연결은 순서와 전달을 제공하지만, 어디에서 원래 레코드 하나가 끝나는지는 말해주지 않는다. FTP는 그 빠진 선언을 자체적으로 삽입했다. 레코드 구조 전송에서는 마지막 EOR을 포함해 모든 EOR이 명시적이었다.
표준 문서들은 로컬 관례를 그대로 실어 보낼 수 없는 이유를 설명한다. 레코드 지향 호스트는 개수 필드나 다른 사적 마커를 저장할 수 있다. 다른 호스트는 그 필드가 무엇을 의미하는지 알 수 없다. 전송 전에 송신자는 자신의 로컬 레코드 표기를 FTP의 협상된 표현으로 번역하고, 전송 후에 수신자는 자신의 시스템이 사용할 수 있는 형태로 역번역한다.
이것은 상호운용성 계약이었지, 호스트 파일 시스템이 서로 닮았다는 약속이 아니었다. 공유되는 부분은 경계 선언이었다. 로컬 저장소는 어디까지나 로컬에 남았다.
이스케이프 뒤의 네 가지 연속
STREAM 문법은 의도적으로 작게 유지되었다:
- 이스케이프 + 1: 레코드의 끝;
- 이스케이프 + 2: 파일의 끝;
- 이스케이프 + 3: 같은 위치에서 레코드의 끝이자 파일의 끝;
- 이스케이프 + 이스케이프: 리터럴 전체 1 데이터 바이트 하나.
결합 코드는 마지막 레코드와 파일이 함께 끝난다는 사실을 말하기 위해 비어 있는 레코드를 새로 발명하는 일을 피했다. 리터럴 형식은 모든 가능한 전송 바이트가 재구성된 데이터에 여전히 나타날 수 있음을 보장했다.
구현체는 센티널을 스캔하고 즉시 경계를 선언할 수 없었다. 두 배로 된 리터럴 짝의 두 바이트를 모두 보존할 수도 없었다. 정확한 디코딩은 한 단계의 선행 검사(look-ahead), 정확한 언인퀴팅, 그리고 전송 바이트와 파일 바이트의 구분을 요구했다.
또한 로컬 읽기에 걸친 상태가 필요했다.RFC 9293은 TCP를 애플리케이션 레코드 서비스가 아닌 순서화된 바이트 스트림 서비스로 정의한다. 이스케이프가 한 수신 연산이 반환하는 마지막 바이트이고 판별자가 다음 수신에서 도착할 수 있다. 그런 분할은 FTP 코드도 레코드 지도도 바꾸지 않는다. 수신 호출이나 TCP 세그먼트를 레코드로 취급하면 송신자가 선언하지 않은 경계를 만들어낸다.
같은 스트림 바이트가 다른 구조에서는 데이터였다
협상된 의미의 가장 뚜렷한 증거는 FTP의 파일 구조 규칙에 나타난다.STRU F이면서 STREAM 모드인 경우, 모든 바이트는 데이터이고 EOF는 데이터 연결을 닫는 것으로 표시된다. 전체 1 바이트는 여기서 이스케이프 역할을 갖지 않는다.
STRU R인 경우에는 파서가 두 바이트 문법을 활성화한다. 그 결과STRU과MODE상태 없이 캡처한 데이터 연결은 불완전하다. 옥텟만으로는 두 배 짝이 한 바이트로 재구성되는지 두 바이트로 남는지, 특정 짝이 레코드를 끝내는지 확정할 수 없다.
연결 종료의 역할도 달라진다. 파일 구조에서는 평범한 EOF 신호를 공급한다. 레코드 구조에서는 EOR 마커가 계속 명시적으로 남고 STREAM 표현은 스트림 안에서 EOF를 진술할 수 있다. "연결이 정상적으로 닫혔다"만 기록하는 모니터는 최종 구조 선언이 도착했는지 놓칠 수 있다.
다른 모드들은 경계를 페이로드 문법 밖으로 옮겼다
FTP는 레코드 의미를 이 하나의 이스케이프 체계에 묶지 않았다. BLOCK 모드에서는 각 데이터 블록이 개수와 디스크립터 플래그를 실었다. 한 디스크립터 비트는 블록이 EOR에서 끝났다고 말하고, 다른 비트는 EOF에서 끝났다고 말하며, 둘을 함께 설정할 수도 있었다. 다른 비트들은 의심스러운 데이터나 재시작 마커를 식별했다.
COMPRESSED 모드도 반복 데이터와 필러를 위한 인코딩을 추가하면서 EOR과 EOF를 위한 디스크립터 형식을 사용했다. 경계 의미는 살아남았지만, 그 온와이어 표현은 MODE에 의존했다.
그래서 구조화된 전송에 대해 "같은 페이로드"라는 진술은 너무 약하다. 두 캡처가 같은 재구성된 데이터 바이트를 담으면서 서로 다른 경계 인코딩을 사용할 수 있다. 반대로 같은 원시 옥텟이 서로 다른 파라미터 조합 아래에서 다른 해석을 가질 수 있다. 신뢰할 수 있는 근거는 제어 플레인 협상, 데이터 스트림 바이트, 디코딩된 구조를 하나로 묶어야 한다.
줄 끝이 곧 레코드 끝은 아니었다
FTP는 줄 끝을 레코드 끝과 분리해서 유지했다. 레코드 구조가 없는 ASCII 텍스트는 인쇄용 줄을 나누기 위해 CRLF를 사용할 수 있고, EBCDIC 텍스트는 NL을 사용할 수 있었다. 레코드 구조 파일은 대신 명시적인 EOR 마커를 실었다.
보이는 텍스트에서 이 경계들이 자주 겹치다 보니 지름길이 유혹할 수 있다. 그러나 레코드가 내장된 줄 끝을 포함하거나 여러 줄에 걸치거나 아예 텍스트적 표현이 없는 순간, 그 지름길은 파괴적이 된다. EOR을 개행 추측으로 바꾸면 원래의 구조를 변형하면서도 여전히 읽을 수 있어 보이는 파일을 만들어낸다.
RFC 959는 ASCII 및 EBCDIC 텍스트 구현체가 레코드 구조를 수용하도록 요구했다. 또한 레코드 지향 호스트와 파일 지향 호스트 사이의 유용하고 가역적인 변환을 강조했다. 동일한 두 시스템이 레코드 없는 텍스트를 주고받을 때는 이진 표현을 사용해 불필요한 변환을 피할 수 있었다. 각 규칙은 같은 원칙을 반영한다: 프로토콜이 진술할 수 있는 구조를 표현으로부터 추론하지 말라.
이후의 최소 요구는 좁아졌다
RFC 1123은 구현 경계를 조정했다. 레코드 구조는 파일 시스템이 이를 지원하는 호스트에만 요구되었다. 네이티브 레코드가 없는 호스트도STRU R을 수용하고 바이트 스트림을 리터럴하게 기록할 수 있었다.
이 선택지는 신중한 문구가 필요하다. 리터럴 보존은 나중에 복구할 수 있도록 인코딩된 근거를 지킬 수 있지만, 로컬 애플리케이션이 네이티브 레코드 지도를 받았음을 증명하지는 않는다. 시스템은 전송 구문을 보존할 수도, 레코드를 재구성할 수도, 레코드를 평탄화할 수도, 요청을 거절할 수도 있다. 이런 결과들이 하나의 무차별적인 성공 주장을 공유해서는 안 된다.
호스트 요구사항은 가능한 한 유용하고 가역적인 변환에 대한 선호를 유지했다. 같은 구조 아래의 복원이 원래 레코드를 재현하지 못한다면, 모든 원시 바이트가 저장소에 도달했다는 이유만으로 수신자가 완전한 의미적 보존을 암시해서는 안 된다.
레지스트리 항목은 파서 테스트가 아니었다
RFC 5797은STRU과MODE를 FTP의 필수 기본 명령으로 유지한다.IANA FTP Commands and Extensions 레지스트리는 이들의 파라미터 설정 역할과 RFC 959 참조를 보존한다.
그 레지스트리는 어휘를 조율한다. 그것이 서버가R인수를 수락하는지, 모든 모드 조합을 지원하는지, 읽기에 걸쳐 이스케이프 상태를 유지하는지, 모든 합법적인 제어 짝을 처리하는지, 레코드를 재구성하는지, 저장소 왕복을 통해 보존하는지 증명하지는 않는다.
이 구분은 그 바이트 자체를 비춘다. 알려진 이름은 의미가 놓일 자리를 만든다. 어떤 의미가 실현되었는지는 오직 주변 상태와 관찰된 행동이 확립한다.
근거에는 디코더가 포함되어야 한다
따라서 방어 가능한 전송 기록에는 파일 해시 그 이상이 담긴다.TYPE,STRU,MODE, 원시 스트림 해시, 디코딩된 데이터 해시, 원시 및 디코딩된 길이, 모든 EOR과 EOF 위치, 최종 파서 상태, 연결 종료 상태, 대상 재구성 결과가 유지되어야 한다.
카나리아 배치는 각 합법적인 제어 짝 앞뒤에 리터럴 두 배 센티널을 놓고, 짝을 수신 호출에 걸쳐 분할하며, 같은 레코드 지도의 STREAM과 BLOCK 인코딩을 비교해야 한다. 종료 시점의 매달린 이스케이프, 알 수 없는 판별자, 누락된 마지막 EOR, 파서 초기화 없이 바뀐 파라미터 조합은 연결 자체가 깨끗하게 완료되더라도 실패한 해석의 근거다.
그 바이트가 두 번 나타나야 했던 이유는 프로토콜이 그 바이트를 희생시키기를 거부했기 때문이다. 레코드 경계는 스트림 안에 살았지만, 오직 송신자와 수신자 사이의 가역적 합의로서만 존재했다.
출처
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





