요약

  • Jon Postel과 Joyce Reynolds의 1983년 5월 RFC 860은 TELNET 옵션 6번 TIMING-MARK를 규정했다. 한쪽이 DO TIMING-MARK를 보내면, 상대는 동의할 경우 자기 버퍼들을 지난 뒤 적절한 위치에 WILL TIMING-MARK를 넣어 돌려보낸다.
  • 첫 명령이 잘못됐는데 사용자가 벌써 다음 내용을 입력한 상황에서, 서버는 표시가 돌아올 때까지 앞서 도착한 글자를 버릴 수 있었다. 그 뒤에는 사용자가 오류를 보고 입력한 새 글자를 다시 해석한다. 표시를 부탁한 쪽이 자기 입력을 정리한다.

사용자는 명령 한 줄을 보내고 답을 기다리는 대신 다음 줄을 쓰기 시작한다. 서버는 첫 줄에서 오타를 찾아 물음표를 보여 준다. 하지만 뒤의 글자들은 이미 사용자의 컴퓨터를 떠났거나 통신 경로를 지나고 있을 수 있다. 그것을 그대로 새 명령으로 읽으면 오타 하나가 뒤의 입력까지 끌고 간다. RFC 860이 붙잡은 문제는 단순하다. 물음표를 보기 전에 친 글자는 어디에서 끝나는가?

TELNET 본체는 양쪽으로 흐르는 연결을 다루고, 옵션 규칙은 추가 동작을 제안하거나 거절할 수 있게 했다. Timing Mark는 그 규칙을 버퍼 정리에 썼다. 이름에 ‘시간’이 들어가지만 여기서 필요한 것은 시각보다 데이터 흐름 속 자리다. 서버가 자기 큐를 읽는 순간과 사람이 화면의 오류를 보는 순간은 서로 떨어져 있다.

서버는 IAC DO TIMING-MARK를 보낸다. 상대가 응하면 돌아오는 흐름의 알맞은 곳에 IAC WILL TIMING-MARK를 넣는다. RFC의 설명에서는 표시가 상대의 출력 버퍼를 통과해 단말 쪽에 이르고, 입력 버퍼를 거쳐 서버로 돌아간다. 서버가 WILL을 받으면 오고 간 데이터에 경계가 생긴다. 그 앞의 글자와 사용자가 물음표를 본 뒤 새로 친 글자를 가를 수 있다.

실제 절차도 적혀 있다. 서버는 먼저 줄을 바꾸고 물음표를 보낸다. 그다음 표시를 요청하고 오류 메시지를 보낸다. WILL이 돌아올 때까지 입력을 읽어 버리다가, 표시 뒤부터 다시 명령으로 받아들인다. 원하는 경계는 사용자가 물음표를 본 뒤 처음 누른 키 바로 앞이다. 서버 자신의 버퍼 길이로 사람의 반응을 추측하는 대신, 단말을 왕복한 표시를 기다리는 셈이다.

쓰레기통의 주인도 정해져 있다. RFC 860에 따르면 불필요한 글자를 버리는 쪽은 DO를 보낸 곳이다. 상대는 믿을 만한 위치에 표시를 놓아 줄 뿐이고, 요청자는 자기 큐를 정리한다. 방향을 바꿔 쓸 수도 있다. 단말이 서버에서 쏟아지는 낡은 출력을 그만 보고 싶다면 표시를 요청하고, WILL이 돌아올 때까지 옛 출력을 숨긴 뒤 새 명령에 따른 출력부터 다시 보여 준다.

응답이 알려 주는 내용은 서로 다르다. WILL은 약속한 곳에 표시를 놓았다는 뜻이다. WON'T는 그 약속을 거절하지만 앞선 데이터가 상대에게 도착했다는 사실은 전한다. DON'T는 앞서 온 WILL을 무시했다고 알린다. 기본 연결에서는 명시적인 동기화를 시도하지 않는다. RFC는 왕복 지연 측정도 활용 예로 들었다. 되돌아오는 지점을 알면 시간을 재기 쉬워지지만, 이 사례에서 표시는 입력의 앞뒤를 가르는 일에 쓰인다.

저자들은 성급한 사용자도 상상했다. 서버의 요청을 예상한 단말이 사용자가 정한 위치에 먼저 WILL을 보내고 입력을 계속할 수 있다. 훗날 DO가 도착하면 단말 소프트웨어가 그 요청을 맞춰 처리해야 한다. 사람 눈에 보이는 ‘지금’과 두 기계의 버퍼 상태가 얼마나 어긋날 수 있는지 보여 주는 장면이다. 작은 표시 하나가 그 어긋남을 지나 서버로 돌아왔다.

화면의 물음표는 한 글자였다. 그 뒤부터 대화를 다시 시작하려면 버퍼를 건너온 답장과, 오래된 입력을 버리겠다는 로컬의 결정이 필요했다. 키보드는 계속 말을 걸었지만 서버는 이제 어느 문장부터 다시 들을지 알았다.