전송 계층
| 항목 | 값 |
|---|---|
| 전송 | TCP (지속 연결, persistent) |
| 기본 포트 | 5225 |
| 소켓 옵션 | TCP_NODELAY 활성 — 작은 패킷을 모았다 보내는 Nagle 지연 없이 즉시 전송 |
| TLS | 선택 — 서버에 인증서가 설정되면 스트림 전체를 단방향 TLS(서버 인증)로 감쌈 |
| 인코딩 | 고정폭 바이너리 필드 + UTF-8 키. 정수는 빅엔디안(network order) |
| 프레임 종료 | \n 한 바이트. \r 처리 없음 |
| 빈 프레임 | \n만(op 자리가 \n) 오면 keep-alive로 조용히 무시 |
| 한 프레임 최대 | 192바이트 — op 포함, \n 제외 (초과 시 E line_too_long 후 연결 종료) |
| 파이프라이닝 | 허용 — 응답 순서가 요청 순서와 다를 수 있음 |
| 유휴 타임아웃 | 없음 — 서버는 조용한 연결을 끊지 않습니다 |
| 프레임 진행 시간 | op 한 바이트를 받은 뒤 헤더와 LF까지 최대 5초. 부분 전송으로 connection을 무한 점유하지 못함 |
연결 수립 순서
- TCP 접속
- 서버가 TLS를 켰다면 TLS 핸드셰이크 — TLS 서버에 평문으로 붙으면 이 단계에서 끊깁니다
- 인증 핸드셰이크 1회
- 이후 락 프로토콜 프레임 교환
프레이밍 규칙
모든 메시지는 한 프레임 = 한 라인입니다.
[ op:1바이트 ][ op별 고정 헤더 ][ 가변 본문 ] \n수신 측은 op를 보고 고정 헤더를 바이트 수 기준으로 먼저 읽은 뒤에야 \n을 스캔해야 합니다. 고정 헤더는 이진 값이라 0x0A(\n)가 들어갈 수 있기 때문입니다(예: lease=10 → 0A). \n 스캔은 마지막 key/텍스트 구간에만 적용됩니다.
| 방향 | op | 고정 헤더 |
|---|---|---|
| 클라이언트 → 서버 | A | 10바이트 (wait:u8 + lease:u8 + owner:u64 BE) |
| 클라이언트 → 서버 | R | 8바이트 (token:u64 BE) |
| 서버 → 클라이언트 | A | 16바이트 (token:u64 BE + owner:u64 BE) |
| 서버 → 클라이언트 | T · B | 8바이트 (owner:u64 BE) |
| 서버 → 클라이언트 | R · N | 8바이트 (token:u64 BE) |
| 서버 → 클라이언트 | M · L · E | 0바이트 (뒤의 주소/사유는 UTF-8 텍스트) |
프레임이 192바이트를 넘거나 malformed이면 서버는 가능한 경우 E를 flush한 뒤 연결을 닫습니다. 클라이언트도 malformed·oversized·알 수 없는 op·상관할 수 없는 E를 connection-fatal로 처리합니다. 이 session에서 이미 한 바이트라도 전송한 acquire는 자동 재시도하지 않고 Indeterminate로 종료합니다.
용어
- 프레임(frame) — 끊김 없는 바이트 스트림(TCP)을 "메시지 하나" 단위로 자른 덩어리. 이 프로토콜에서는
\n으로 끝나는 한 줄이 프레임 하나입니다. - 빅엔디안(big-endian) — 정수를 큰 자릿수 바이트부터 적는 순서. 네트워크 프로토콜의 표준이라 network order라고도 부릅니다.
- 파이프라이닝(pipelining) — 앞 요청의 응답을 기다리지 않고 다음 요청을 연달아 보내는 것. 왕복 지연이 겹쳐져 처리량이 올라갑니다.
- keep-alive — 연결이 살아 있음을 알리기 위해 주기적으로 보내는 무의미한 신호. 여기서는 빈 프레임(
\n)이 그 역할을 합니다.