LabHub
开始
学习 学习路径 课程

构建 EAI 中间层

切分、校验并翻转标准报文头

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

LH-STD 표준 헤더(80바이트)를 오프셋까지 이해하고, 파싱·검증·응답 생성·GUID 발급·스트림 분리를 직접 구현한다.

왜 중요한가

중계 계층은 헤더만 보고 판단한다. 헤더를 자르는 위치가 한 바이트만 어긋나도 라우팅·추적·중복 방지가 전부 엉뚱한 값을 본다. 그리고 전문은 TCP 스트림 위로 오므로, 길이 필드를 믿고 바이트로 자르는 습관이 없으면 긴 전문에서만 깨지는 버그를 운영에서 처음 만난다. 형식이 틀린 전문을 추측해서 처리하지 않고 E102 로 거절하는 것도 이 계층의 책임이다.

단계

  1. 정의서 /opt/lab/fixtures/eaimw/header/SPEC.md 를 읽고 /root/eaimw/header/layout.csv 를 만든다. 머리글 field,offset,length, 헤더 9개 필드를 순서대로, 오프셋은 0부터 센 바이트 위치.
  2. 수신함 /opt/lab/fixtures/eaimw/header/inbox/ 의 모든 파일에 대해 전문길이 필드(앞 4바이트)와 실제 바이트 수(파일 크기 - 4)를 비교해 /root/eaimw/header/lencheck.csv 를 만든다. 머리글 file,declared,actual,result, 파일 이름순, result 는 OK 또는 LEN_MISMATCH.
  3. /root/eaimw/header/hdr.py 를 만든다. python3 hdr.py <파일> 이 헤더를 JSON 으로 출력하고(키: MSG_LEN·TX_CODE·GUID·SND_ORG·RCV_ORG·MSG_TYPE·RSP_CODE·SEND_TS·BODY_LEN, 값은 앞뒤 공백 제거, MSG_LEN·BODY_LEN 은 정수) 0 으로 끝난다. 정의서 5절의 형식 오류면 첫 줄에 E102 <사유> 를 출력하고 종료 코드 2 로 끝난다.
  4. /root/eaimw/header/reply.py 를 만든다. python3 reply.py <요청파일> <응답코드4자리> 가 응답 전문을 표준출력(바이트)으로 낸다 — 거래코드·GUID 유지, 송수신 기관 맞바꿈, 구분 R, 응답코드 채움, 전송일시는 지금(한국 시각), 본문 없음, 전문길이 재계산. 응답코드가 4자리가 아니면 0 이 아닌 코드로 끝난다.
  5. /root/eaimw/header/guid.py 를 만든다. 실행할 때마다 소문자 16진수 32자(전부 0 금지) GUID 한 줄을 출력한다. 예측 가능한 random 이 아니라 secretsuuid 로 발급한다.
  6. /root/eaimw/header/split.py 를 만든다. 전문 여러 개가 이어 붙은 파일(TCP 로 받은 바이트 그대로)을 받아 전문마다 거래코드 GUID 본문바이트수 한 줄을 출력하고 0 으로 끝난다. 마지막 전문이 잘려 있으면 완전한 것들을 먼저 출력한 뒤 INCOMPLETE <남은바이트수> 를 출력하고 종료 코드 3 으로 끝난다.
  7. 수신함 전체를 판정해 /root/eaimw/header/report.csv 를 만든다. 머리글 file,tx_code,guid,result, 파일 이름순. 정상은 OK, 거절한 전문은 tx_code·guid 를 비우고 E102.

참고

정의서를 오프셋으로 옮긴다

/opt/lab/fixtures/eaimw/header/SPEC.md 의 헤더 9개 필드를 /root/eaimw/header/layout.csv 로 옮긴다(field,offset,length, 오프셋은 0부터).

오프셋은 앞 필드들의 길이 합입니다. MSG_LEN 이 0·4 이면 TX_CODE 는 4 에서 시작합니다. 마지막 필드까지 더하면 80 이어야 합니다.

전문길이를 바이트로 대조한다

/opt/lab/fixtures/eaimw/header/inbox/ 의 모든 파일에 대해 선언 길이와 실제 길이를 비교해 /root/eaimw/header/lencheck.csv 를 만든다.

선언 길이는 head -c 4, 실제 길이는 stat -c %s 에서 4 를 뺀 값입니다. 한글이 든 파일을 편집기로 열어 세면 글자 수가 나옵니다 — 필요한 것은 바이트 수입니다.

파서를 만든다 — 틀리면 거절한다

/root/eaimw/header/hdr.py 가 헤더를 JSON 으로 출력하고, 형식 오류면 첫 줄 E102 와 종료 코드 2 로 거절한다.

open(f,'rb') 로 읽고 bytes 를 오프셋대로 자릅니다. 길이 대조·거래코드 정규식·GUID 소문자 16진수·기관 숫자 3자리·Q/R·datetime.strptime 으로 날짜 검증 — 정의서 5절 목록 그대로입니다.

요청을 뒤집어 응답을 만든다

/root/eaimw/header/reply.py <요청파일> <응답코드> 가 응답 전문을 표준출력으로 낸다.

3단계의 parse 를 import 해서 씁니다(from hdr import parse). 바이트를 내보낼 때는 print 가 아니라 sys.stdout.buffer.write 입니다. 전문길이는 나머지를 다 만든 뒤 len 으로 계산하세요.

GUID 를 발급한다

/root/eaimw/header/guid.py 가 실행할 때마다 소문자 16진수 32자 GUID 를 한 줄 출력한다(전부 0 금지, secrets 또는 uuid).

secrets.token_hex(16) 은 16바이트 난수를 16진수 32자로 줍니다. uuid.uuid4().hex 도 같은 모양입니다. 시각으로 만들면 같은 밀리초에 겹칩니다.

TCP 스트림을 전문으로 자른다

/root/eaimw/header/split.py 가 이어 붙은 전문을 길이 필드로 잘라 한 줄씩 출력하고, 잘린 꼬리는 INCOMPLETE 과 종료 코드 3 으로 알린다.

pos 를 0 에서 시작해 buf[pos:pos+4] 를 길이로 읽고 pos+4+길이 까지를 한 전문으로 자릅니다. 남은 바이트가 길이보다 모자라면 그것이 잘린 꼬리입니다.

수신함 판정 보고서

수신함 전체를 판정해 /root/eaimw/header/report.csv 를 만든다(file,tx_code,guid,result — OK 또는 E102).

3단계의 hdr.py 를 파일마다 돌려 종료 코드로 가릅니다. 거절된 전문의 거래코드를 억지로 읽어 적지 마세요 — 형식이 틀린 전문의 필드는 믿을 수 없습니다.