응용 프로토콜을 가진 통신프로그램을 짜는데.. parser?
안녕하세요. 사회 초년생 코더입니다.
다른게 아니라 이번에 프로젝트에서 서로 메세지를 주고 받는 응용프로그램을 짜게 되었습니다.
자세하게 설명은 못하겠지만, 앞에 응용Level의 정의된 헤더를 붙이고, 그 뒤에는 임의 구조의 어떤
메세지가 붙습니다.
헤더야 그냥 하드코딩으로 처리하게 하면 되니까 큰 문제는 아니고 뒤에 오는 메세지 포멧처리 하는데
고민이 좀 생겼는데 예를 들면 이런 식이지요..
'잡담'이라는 메세지 형식은
제목 200byte
본문내용 1000byte
'자재현황' 이라는 메세지 형식은
제품코드 2byte
제품이름 50byte
비고 100byte
'인사보고' 라는 메세지 형식은
직급코드 2byte
인사이동 2byte
이름 10byte
비고 100byte
같은 메세지 형식이 규약된 문서가 있고 저는 이런 메세지를 주고 받는 프로그램을 짜야하는겁니다.
위의 예시들은 저런 내용을 발췌해서 적은게 아니라 생각나는 대로 예시를 만들어 버린것이기 때문에
실제 프로젝트랑은 좀 상이한 내용이 됬는데 맥락은 비슷합니다. 그리고 따로 DB를 쓴다거나 하지는
않습니다.
문제는 저런 주고 받는 메세지 형식이 언제든지 추가/삭제 될수 있으며 구조의 변경이 올 수 가
있다는겁니다. 결국 저런 메세지들을 처리하는 부분을 하드코딩으로 박아놓으면 만들때는 편할지
모르겠는데, 매번 소스코드에 손을 대야 하는것이 부담스러워서 개발시간이 좀 걸리더라도
외부에 저런 메세지 구조들이 정의된 데이터 파일을 하나 만들어놓고 run-time에 응용프로그램에서는
그 파일이 접근해서 '어떤 어떤 메세지들을 사용하고, 구조는 이렇다' 라는걸 파악하게 해서
동적으로 프로그램에 메세지 구조가 변한다던가, 사용하는 메세지가 추가 됬다던가 하는걸
알 수 있도록 하게 하고 싶습니다.
약간 틀린 관계지만, 스타크래프트와 스타크래프트 맵 에디터의 관계라고 할까요?
본 응용프로그램은 데이터 파일을 읽어서 구조를 파악하는 parser가 주가 되고
외부에 그 메세지 구조들이 정의된 파일을 관리하는 툴을 따로 짜서 데이터파일만 가지고 수정을
하게되면 응용프로그램 소스를 건들 필요가 없도록 하는 것이 목적입니다.
그래서 다음과 같은 파일을 만들도록 하는 프로그램을 짯습니다(외부 툴)
메세지의 구조를 입력해서 파일로 만드는 프로그램인데 위의 예시를 하나 옮겨보면
'잡담.txt'
----------------
1/제목/200
2/본문내용/1000
----------------
이런 메세지 구조가 담긴 파일 하나를요.
막상 만들어 놓고 보니 이전의 하드코딩으로 처리한다고 하면 run-time 이전에 이미
struct로 char subject[20]; char content[1000]; 같이 이미 구조를 담고있는 구조체를
코딩해놓기 때문에 UI에서 입력받은 값을 구조체에 넣는다거나, 받은 데이터를 구조체에 복사하여
필드별로 떼어낸다던가 하는 행위를 코드에서 할 수 있었는데 이제는 구조를 run-time에 읽어야
하니 그런 코드를 작성 할 수 없었습니다. 그리고 run-time에서 읽는다고 하더라도 이전과 같은
구조체의 사용이 아니라.
typedef struct tagMsg
{
int index;
char fieldname[xx];
int size;
}__FieldRecord
(이것도 그냥 예시코드입니다)
같이 직접적인 메세지 구조를 정의한 구조체가 아닌 그 구조가 정의된 파일을 읽기위한 구조체 밖에
코딩할때 쓸 수가 없으니까요. 뭐 이거는 해결가능할것 같습니다만.
아무 생각없이 그냥 그렇게 하면 되겠거니 했는데 막상 설계를 하다보니 경험없는 초짜에게는
방법론이란게 떠오르질 않더라구요.
딱히 어떤 검색어로 정보검색을 해야 될지도 몰라서 마구잡이로 검색하다 보니
xml, data driven, script, parser, interpreter 등으로 검색을 하게 되는데,
제가 응용력이 딸리는건지 어떻게 적용을 해야될지 감이 잘 안잡힙니다.
이런저런 넋두리들을 늘어놓은것 같고, 솔직히 말하면 '이 라이브러리를 쓰세요!' 하고 링크하나
떨렁 나오면 만세를 외치면서 쓰고 싶지만, 그러기도 힘들거 같고, 사실 원하는건 이런 상황에서
어떤 테크닉을 써야 하는지, 아니면 최소한 어떤 검색어를 가지고 검색을 해봐야 힌트를 얻을 수
있을지에 대한 조언을 구하고 싶습니다.
PS. 개발환경은 윈도우에 MFC 환경이지만 메세지를 처리하는 부분은 unix 시스템에서도 돌려야 하는 상황입니다
공용체를 써보시는건 어떨까요
기존의 코드와도 호환에 별 문제가 없을듯 하구요. 공용체 내에 구조체가 들어가는 구조라면 기존 코드를 재사용하는데도 큰 어려움이 없을듯 합니다.
거창하게 XML이나
거창하게 XML이나 parser, interpreter는 생각하지 않으셔도 됩니다.
그냥 메시지 포맷을 정의해놓고 메시지의 앞쪽에 적어놓은 타입값에 따라서
특정 메시지 용 구조체를 type cast하는 방법을 쓰세요.
신경작용제님 말씀처럼 공용체를 쓰기도 합니다.
융통성 있게 짜는 방법으로 json을 사용할 수도 있겠죠.
배보다 배꼽이 더 클수도 있습니다만, xml만큼 복잡하지 않으면서도 알려진 언어들에 대한 다양한 parser 역시 제공됩니다.
data의 구조가 key-value쌍들로 이루어진 형태를 고려한다면 json 추천
http://ko.wikipedia.org/wiki/JSON
http://en.wikipedia.org/wiki/JSON
http://www.json.org/json-ko.html
ps) 아주 일반적인 (외부 format(schema)정의 + schema, sematic 해석기)를 직접 구현하는 것은 현실성이 없어보입니다.
예시해주신 정도라면 어차피 적당 선에서 받는 쪽에서 필요한 부분을 가공하는 것이니 각 entry 의 가변 포맷(data type, 크기) 정도만 자동으로 처리할 수 있게 하는 것이 낫지 않을까요?
한 가지 조언을 드리자면
일단, 저 처럼 패킷 정의를 외부에 빼 놓고 어플리케이션을 만든다고 하도
새로운 패킷이 추가될 경우 컴파일이 필요할 수도 있습니다. 아마 필요하지 않은 경우가 더 드물 겁니다.
(간단한 액션 스크립트를 정의해서 메시지 처리를 스크립트화 하지 않는 이상에는 말이죠)
왜냐하면 새로운 패킷은 뭔가 기존에 컴파일 되서 돌아가고 있는 어플리케이션에 없는 기능을
필요로 할 가능성이 크거든요. 정말로 컴파일 혹은 프로스세스 중단이 크리티컬한 상황이 아닌 이상
유지보수가 쉬운 코드를 만든다고 생각하시는 것이 쉽고 실제로 거기에 많은 노력을 기울이는게
이후에 일이 편해집니다.
위에 여러분들께서 답변해주신 것처럼 유니온을 쓰던 각 메시지 타입별로 바디를 스트럭쳐로 정의하건
혹은 캐릭터 스트림으로 받아서(name=value)처리하건 별 차이가 없습니다.
여기까지가 대략 조언이구요. 질문하신 내용에 좀 답변을 드리자면,
일단 정확한 프로토콜의 용도도 어플리케이션의 분야도 모르겠으나 일반적인 경우라면 헤더에 따라
바디가 정해지는 경우 보통 프로토콜에 나온 헤더(1)/바디(다수) 스트럭쳐를 정의해서 사용합니다.
그리고 어플리케이션이 하는 일은 보통
1. 소켓에서 헤더길이만큼 읽음.
2. 헤더에서 메시지(바디) 판별.
3. 소켓에서 바디만큼 읽음.
4. 메시지 처리
이 과정의 반복입니다. 물론 예외처리나 기타 자질구레한 것들이 들어가면서 지저분해 질 순 있습니다.
이와 관련해선 왠간한 소켓 통신 예제를 찾아보면 나오지 않을까 싶네요.
그럼...
댓글 달기