2010-07-21 20 views

Répondre

2

Je trouve this thread assez clair, il contient aussi des (petits) exemples même s'ils sont des exemples assez «extrêmes». Des exemples plus «réalistes» utilisant des étiquettes IMPLICIT peuvent être trouvés dans this page.

+1

pour moi comme exemples de débutants ne sont pas assez claires –

+0

j'ai été perdu dans les exemples – achabahe

23

En ASN.1, le marquage sert en fait à deux fins: le typage et le nommage. Taper signifie indiquer à un en-/décodeur quel type de type de données est (est-ce une chaîne, un entier, un booléen, un ensemble, etc.), le nommage signifie que s'il y a plusieurs champs du même type et certains (ou tous) sont facultatifs, il indique à l'en-/décodeur pour quel champ cette valeur est.

Si vous comparez ASN.1 à, disons, JSON, et vous regardez les données JSON suivantes:

"Image": { 
    "Width": 800, 
    "Height": 600, 
    "Title": "View from 15th Floor" 
} 

Vous remarquerez que, dans tous les domaines JSON est toujours explicitement nommé (« Image » , "Largeur", "Hauteur", "Titre") et soit explicitement ou implicitement typé ("Title" est une chaîne, car sa valeur est entourée de guillemets, "Width" est un entier, car il n'a pas de guillemets, seulement des chiffres , ce n'est pas "nul", "vrai" ou "faux", et il n'a pas de période décimale).

En ASN.1 cette donnée serait:

Image ::= SEQUENCE { 
    Width INTEGER, 
    Height INTEGER, 
    Title UTF8String 
} 

Cela fonctionnera sans marquage spécial, ici que les balises universelles sont nécessaires. Universal tags ne nommez pas les données, elles ne font que saisir des données, de sorte que en-/decoder sait que les deux premières valeurs sont des entiers et que le dernier est une chaîne. Que le premier entier est Largeur et le second est Hauteur n'a pas besoin d'être codé dans le flux d'octets, il est défini par leur ordre (les séquences ont un ordre fixe, les ensembles ne le font pas. utilisé).

changer maintenant le schéma comme suit:

Image ::= SEQUENCE { 
    Width INTEGER OPTIONAL, 
    Height INTEGER OPTIONAL, 
    Title UTF8String 
} 

Bon, maintenant nous avons un problème. Supposons que les données suivantes sont reçues:

INTEGER(750), UTF8String("A funny kitten") 

Qu'est-ce que 750? Largeur ou Hauteur? Peut-être Width (et Height est manquant) ou pourrait être Height (et Width is missing), les deux ressembleraient à un flux binaire. Dans JSON, cela serait clair car chaque donnée est nommée, ce qui n'est pas le cas en ASN.1. Maintenant, un type seul ne suffit pas, maintenant nous avons aussi besoin d'un nom. C'est là que les étiquettes non universelles entrent dans le jeu. Changer à:

Image ::= SEQUENCE { 
    Width [0] INTEGER OPTIONAL, 
    Height [1] INTEGER OPTIONAL, 
    Title UTF8String 
} 

Et si vous recevez les données suivantes:

[1]INTEGER(750), UTF8String("A funny kitten") 

Vous savez que 750 est la hauteur et non la largeur (il n'y a tout simplement pas de largeur). Ici, vous déclarez une nouvelle étiquette (dans ce cas spécifique au contexte) qui sert à deux fins: Elle indique à l'en-/décodeur qu'il s'agit d'une valeur entière (typage) et lui indique la valeur entière qui est (nommage).

Mais quelle est la différence entre le marquage implicite et le marquage explicite? La différence est que le marquage implicite ne nomme que les données, l'en-/décodeur doit connaître le type implicitement pour ce nom, tandis que les noms de marquage explicites et saisissent explicitement les données.

Si le marquage est explicite, les données seront envoyées comme:

[1]INTEGER(xxx), UTF8String(yyy) 

même si un décodeur n'a aucune idée que [1] signifie hauteur, il sait que les octets « xxx » doivent être analysés/interprété comme une valeur entière. Un autre avantage important du marquage explicite est que le type peut être modifié dans le futur sans changer l'étiquette. Par exemple.

Length ::= [0] INTEGER 

peut être changé pour

Length ::= [0] CHOICE { 
    integer INTEGER, 
    real REAL 
} 

Tag [0] signifie encore longueur, mais maintenant la longueur peut être un entier ou une valeur en virgule flottante. Comme le type est codé explicitement, les décodeurs sauront toujours comment décoder correctement la valeur et cette modification est donc compatible avec les versions antérieure et aval (au moins au niveau du décodeur, pas nécessairement rétrocompatible au niveau de l'application).

Si le marquage est implicite, les données seront envoyées comme:

[1](xxx), UTF8String(yyy) 

Un décodeur qui ne sait pas ce que [1] est, ne connaît pas le type de « xxx » et ne peut donc pas analyser/interpréter correctement ces données. Contrairement à JSON, les valeurs dans ASN.1 sont juste des octets. Donc "xxx" peut être un, deux, trois ou peut-être quatre octets et comment décoder ces octets dépend de leur type de données, qui n'est pas fourni dans le flux de données lui-même. Changer également le type de [1] va briser les décodeurs existants à coup sûr. OK, mais pourquoi quelqu'un utiliserait-il un marquage implicite? N'est-il pas préférable de toujours utiliser le marquage explicite? Avec le marquage explicite, le type doit également être codé dans le flux de données, ce qui nécessite deux octets supplémentaires par étiquette. Pour les transmissions de données contenant plusieurs milliers (peut-être même des millions) de tags et où chaque octet compte (connexion très lente, paquets minuscules, perte de paquets élevée, dispositifs de traitement très faibles) et où les deux côtés connaissent tous les tags personnalisés, pourquoi gaspiller la bande passante , mémoire, stockage et/ou temps de traitement pour encoder, transmettre et décoder des informations de type inutiles? Gardez à l'esprit qu'ASN.1 est un standard plutôt ancien et qu'il était destiné à obtenir une représentation très compacte des données à un moment où la bande passante du réseau était très coûteuse et les processeurs plusieurs centaines de fois plus lents qu'aujourd'hui. Si vous regardez tous les transferts de données XML et JSON d'aujourd'hui, il semble ridicule de penser même à économiser deux octets par tag.

+0

Référence: https://osqa-ask.wireshark.org/questions/8277/difference-between-implicit-and-explicit -tags-asn1. Ici, a) A :: = INTEGER avec la valeur 5 est codé comme hex 02 01 05, b) B :: = [2] IMPLICIT INTEGER avec la valeur 5 est codé comme hex 82 01 05 et c) C :: = [2 ] EXPLICIT INTEGER avec la valeur 5 est codé comme hexadécimal A2 03 02 01 05. Quelqu'un pourrait-il expliquer s'il vous plaît le cas b et le cas c! – AVA

+0

@AVA Si vous avez une question, pourquoi ne posez-vous pas une question? Pourquoi mettez-vous votre question dans un commentaire? L'objectif est de poser des questions, alors allez-y et posez une question. – Mecki