C - 직렬화 기술
네트워크를 통해 전송할 데이터를 직렬화하기 위해 코드를 작성하고 있습니다.현재 저는 다음과 같은 기본 절차를 사용합니다.
- 을 생성합니다.
void*
완충제 - 다음과 같은 모든 바이트 순서 지정 작업 적용
hton
네트워크를 통해 전송할 데이터의 패밀리 - 사용하다
memcpy
메모리를 버퍼에 복사합니다. - 네트워크를 통해 메모리 전송
문제는 다양한 데이터 구조(종종 무효* 데이터가 포함되어 있어 바이트 순서를 신경 쓸 필요가 있는지 여부를 알 수 없음)에서 코드가 각 데이터 구조에 매우 특정한 직렬화 코드로 인해 매우 비대해지고 전혀 재사용할 수 없다는 것입니다.
이것을 더 쉽게/ 덜 추하게 만드는 C의 좋은 직렬화 기술은 무엇입니까?
-
참고: 특정 프로토콜에 묶여 있기 때문에 데이터를 직렬화하는 방법을 자유롭게 선택할 수 없습니다.
각 데이터 구조에 대해 serialize_X 함수(여기서 X는 구조 이름)를 사용하여 X에 대한 포인터와 불투명 버퍼 구조에 대한 포인터를 가져오고 적절한 serializing 함수를 호출합니다.버퍼에 쓰고 출력 인덱스를 업데이트하는 serialize_int와 같은 기본 요소를 제공해야 합니다.원시 요소는 reserve_space(N)와 같은 것을 호출해야 합니다. 여기서 N은 데이터를 쓰기 전에 필요한 바이트 수입니다.reserve_space()는 void* 버퍼를 재할당하여 최소 현재 크기에 N바이트를 더한 크기로 만듭니다.이를 가능하게 하려면 버퍼 구조에 실제 데이터에 대한 포인터, 다음 바이트를 쓸 인덱스(출력 인덱스) 및 데이터에 할당된 크기가 포함되어야 합니다.이 시스템에서 모든 serialize_X 함수는 다음과 같이 매우 간단해야 합니다.
struct X {
int n, m;
char *string;
}
void serialize_X(struct X *x, struct Buffer *output) {
serialize_int(x->n, output);
serialize_int(x->m, output);
serialize_string(x->string, output);
}
프레임워크 코드는 다음과 같습니다.
#define INITIAL_SIZE 32
struct Buffer {
void *data;
size_t next;
size_t size;
}
struct Buffer *new_buffer() {
struct Buffer *b = malloc(sizeof(Buffer));
b->data = malloc(INITIAL_SIZE);
b->size = INITIAL_SIZE;
b->next = 0;
return b;
}
void reserve_space(Buffer *b, size_t bytes) {
if((b->next + bytes) > b->size) {
/* double size to enforce O(lg N) reallocs */
b->data = realloc(b->data, b->size * 2);
b->size *= 2;
}
}
이를 통해 필요한 serialize_() 함수를 모두 구현하는 것은 매우 간단할 것입니다.
편집: 예:
void serialize_int(int x, Buffer *b) {
/* assume int == long; how can this be done better? */
x = htonl(x);
reserve_space(b, sizeof(int));
memcpy(((char *)b->data) + b->next, &x, sizeof(int));
b->next += sizeof(int);
}
편집: 또한 내 코드에 잠재적인 버그가 있습니다.오류 처리를 위한 규정도 없고 완료 후 버퍼를 해제할 수 있는 기능도 없으므로 사용자가 직접 이 작업을 수행해야 합니다.저는 제가 사용할 기본 아키텍처에 대한 시연을 하고 있었습니다.
직렬화를 직접 구현하려고 하지는 마십시오.수많은 작업이 수행되었으며 기존 솔루션을 사용해야 합니다. 예: protobfs: https://github.com/protobuf-c/protobuf-c
또한 다른 많은 프로그래밍 언어와 호환되는 장점이 있습니다.
저는 도서관을 이용하는 것을 제안합니다.
저는 기존 도서관이 마음에 들지 않아 우리의 삶을 편하게 하기 위해 빈 도서관을 만들었습니다.
다음은 사용 예입니다.
binn *obj;
// create a new object
obj = binn_object();
// add values to it
binn_object_set_int32(obj, "id", 123);
binn_object_set_str(obj, "name", "Samsung Galaxy Charger");
binn_object_set_double(obj, "price", 12.50);
binn_object_set_blob(obj, "picture", picptr, piclen);
// send over the network
send(sock, binn_ptr(obj), binn_size(obj));
// release the buffer
binn_free(obj);
프로토콜 제약 조건이 무엇인지 알면 도움이 되지만 일반적으로 사용자의 옵션은 상당히 제한적입니다.데이터가 각 구조체에 대해 (구조체)의 바이트 배열 크기를 결합할 수 있는 정도라면 일을 단순화할 수 있지만, 설명에 따르면 포인터를 전송하는 경우(보이드 * 데이터를 언급함) 수신기에서 해당 포인트가 유효할 가능성이 매우 낮습니다.데이터가 메모리의 동일한 위치에 나타나는 이유는 무엇입니까?
"C" 프로그램의 경우, "자동" 직렬화를 위한 좋은 옵션이 많지 않은 경우."포기"하기 전에 SUNRPC 패키지(rpcgen 및 친구)를 검토할 것을 제안합니다.다음을 포함됩니다.
- 데이터 구조를 설명하는 "XDR" 언어(기본적으로 "C"의 하위 집합)인 사용자 정의 형식입니다.
- RPC 생성 - 직렬화의 클라이언트 및 서버 측을 자동으로 생성할 수 있습니다.
- 거의 모든 유닉스 환경과 함께 제공되는 런타임 라이브러리.
프로토콜과 코드에는 인터넷 표준이 있습니다.
- https://www.rfc-editor.org/rfc/rfc5531 - RPC
- https://www.rfc-editor.org/rfc/rfc4506 - XDR
이 도서관은 당신을 도울 수 있습니다.https://github.com/souzomain/Packer
그것은 사용하기 쉽고 코드는 공부하기에 깨끗합니다.
사용 예:
PPACKER protocol = packer_init();
packer_add_data(protocol, yourstructure, sizeof(yourstructure));
send(fd, protocol->buffer, protocol->offset, 0);
packer_free(protocol);
언급URL : https://stackoverflow.com/questions/6002528/c-serialization-techniques
'programing' 카테고리의 다른 글
Oracle 'printf' 등가 (0) | 2023.07.28 |
---|---|
레일즈 마이그레이션에서 검사 제약 조건을 추가하려면 어떻게 해야 합니까? (0) | 2023.07.28 |
데이터 프레임 인덱스에 함수 적용 (0) | 2023.07.28 |
조각에서 활동 메서드 호출 (0) | 2023.07.28 |
상위 구성 요소의 Ajax 업데이트에서 하위 구성 요소를 제외하는 방법은 무엇입니까? (0) | 2023.07.28 |