Data Structure를 (파일에 저장하고) 네트워크를 통해 전송하는 수 많은 방법들이 있다.
padding없이 만든 struct, POD class 등 을 그대로 memcpy할 수도 있는데, Endian 처리를 잘 해줘야 하며 유지보수할 때 실수를 할 가능성이 많다.
플랫폼뿐만 아니라 프로그래밍 언어 사이에서도 Data를 교환할 수 있도록 한 여러 라이브러리, 프레임워크 등 이 많다. protocol buffers, thrift, avro, MessagePack 등 Data Serialization뿐 아니라 low level network I/O 및 RPC 메커니즘까지 제공하는 것들도 있다. Go는 Go로 작성된 프로그램끼리 Data를 주고받을 수 있도록 한 gob이라는 패키지도 있다. C++ boost 라이브러리에는 Serialization이 있는데, Binary format을 네트워크를 통해 잘 전송하는 것을 보장하지 않는다고 한다 (XML 등 Text 형식은 사용 가능).
이러한 라이브러리들을 사용하기 위해서, 목적에 맞는 것들을 잘 선택해야 한다. 최근에 지금 일하고 있는 회사에서 MessagePack을 사용하기로 했다 (MessagePack 및 boost asio 사용 예).
그런데, 이런 라이브러리들은 너무 멋지다(Fancy). The Practice of Programming의 한 장에서 소개하는 Packet 처리 방식은 내게 좋은 영감을 주었다. printf의 타입을 명시하는 _little language_를 차용한 이 방식은 Erlang의 pattern matching이나 Python의 struct에서도 관찰할 수 있다고 생각한다.
Pattern matching 연산으로 IPv4 data를 파싱하는 erlang code (Programming Erlang - Joe Armstrong):
...
case Dgram of
<<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
ID:16, Flgs:3, FragOff:13,
TTL:8, Proto:8, HdrChkSum:16,
SrcIP:32
...
Packing, Unpacking three integers:
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
pattern matching은 규칙을 명시하는 little language의 수준을 뛰어 넘는 것으로 보인다. Python struct module의 hhl
과 같은 문자열은 little language의 좋은 예가 된다.
The Practice of Programmig에서는 위와 같은 예를 소개하고 있다:
이 예는 어떤 상용 네트워크 프로토콜의 실제 코드에 기반한다. 필자가 일단 이 접근방식이 통할 거라고 깨닫자마자, 몇천 줄 정도 되던 반복적이고 에러가 생기기 쉬웠던 코드가, 유지보수하기 쉬운 몇백 줄 정도로 줄어들었다. 표기법이 혼란을 확 잠재운 것이다.
struct는 Python struct module과 비슷하게 구현한 C Library이다. 이 코드에 Null-terminated string, blob data 등 을 추가한 코드는 여기에서 확인할 수 있다.
Comments !