如何在互联网数据传输中使用ASN.1?asn1c生成代码使用疑问
Hey there! Let's tackle your questions one by one and walk you through a complete example to serialize and send your Rectangle data.
Why use INTEGER_t instead of int?
ASN.1's INTEGER type is designed to support arbitrary-precision integers (way larger than what a standard int or even long can hold). The INTEGER_t type generated by asn1c is a helper structure that wraps the raw integer data along with metadata needed for ASN.1 encoding/decoding:
- It stores the integer as a byte buffer (to handle big numbers)
- Tracks the length of that buffer
- Includes internal context for encoding state
This aligns with ASN.1's flexibility, even if you're only using small integers right now—it's the compiler enforcing the standard.
What's with the _asn_ctx field in the struct?
That _asn_ctx isn't a nested struct you need to worry about—it's an internal context object used by asn1c's runtime to handle things like:
- Parsing across buffer boundaries (useful for streaming data)
- Tracking encoding/decoding state
- Managing errors during the process
You don't need to modify or interact with _asn_ctx directly—it's handled automatically by the asn1c-provided functions. The Rectangle_t struct itself is straightforward: it just holds your two integer fields plus this internal bookkeeping data.
Step-by-Step: Serialize rect={10,20} and Send It
1. Compile the asn1c-generated files
First, compile all the generated .c files (including Rectangle.c, INTEGER.c, asn_SEQUENCE_OF.c, etc.—you'll see them in your directory) into object files:
gcc -c *.c
2. Example Code to Serialize, Send, and Deserialize
Here's a complete example that initializes your Rectangle, encodes it to BER format, simulates sending it, then decodes it back:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "Rectangle.h" #include "ber_encoder.h" #include "ber_decoder.h" int main() { // Step 1: Initialize the Rectangle struct Rectangle_t rect; memset(&rect, 0, sizeof(Rectangle_t)); // Zero-initialize all fields // Set height=10 and width=20 using asn1c helper functions if (asn_INTEGER_set(&rect.height, 10) != 0) { fprintf(stderr, "Failed to set height value\n"); return 1; } if (asn_INTEGER_set(&rect.width, 20) != 0) { fprintf(stderr, "Failed to set width value\n"); return 1; } // Step 2: Encode the Rectangle to BER format asn_enc_rval_t enc_result; uint8_t *ber_buffer = NULL; size_t ber_buffer_size = 0; // DER is a strict subset of BER, suitable for most use cases enc_result = der_encode_to_buffer(&asn_DEF_Rectangle, &rect, &ber_buffer, &ber_buffer_size); if (enc_result.encoded == -1) { fprintf(stderr, "Encoding failed: %s\n", enc_result.failed_type->name); return 1; } printf("Encoded BER buffer size: %zu bytes\n", ber_buffer_size); // Step 3: Simulate sending the buffer (in real code, use sockets/files) uint8_t *sent_buffer = malloc(ber_buffer_size); memcpy(sent_buffer, ber_buffer, ber_buffer_size); // Step 4: Decode the received buffer back to Rectangle_t Rectangle_t *decoded_rect = NULL; asn_dec_rval_t dec_result = ber_decode(NULL, &asn_DEF_Rectangle, (void **)&decoded_rect, sent_buffer, ber_buffer_size); if (dec_result.code != RC_OK) { fprintf(stderr, "Decoding failed at byte %zu\n", dec_result.consumed); return 1; } // Extract and print decoded values long height_val, width_val; asn_INTEGER_get(&decoded_rect->height, &height_val); asn_INTEGER_get(&decoded_rect->width, &width_val); printf("Decoded Rectangle: height=%ld, width=%ld\n", height_val, width_val); // Cleanup allocated memory properly ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rect); free(ber_buffer); free(sent_buffer); return 0; }
3. Compile and Run the Example
Link your example code with the compiled object files:
gcc -o rectangle_example rectangle_example.o *.o ./rectangle_example
Key Notes
- Helper Functions: Always use
asn_INTEGER_set()andasn_INTEGER_get()to convert between standard integers andINTEGER_t—never directly modify the internal fields ofINTEGER_t. - Other Formats: For PER or XER encoding/decoding, replace the BER functions with
per_encode_to_buffer()/per_decode()orxer_encode_to_buffer()/xer_decode()respectively. - Memory Safety: Use
ASN_STRUCT_FREE()to clean up ASN.1 structures—it ensures all internal buffers are freed properly, avoiding memory leaks.
内容的提问来源于stack exchange,提问作者chenkh

