Socket TCP et décalage d'octet [Résolu]

Signaler
Messages postés
6
Date d'inscription
vendredi 24 avril 2009
Statut
Membre
Dernière intervention
22 juin 2009
-
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
-
Bonjour à tous, voilà je vous explique mon problème en espérant être clair et précis.
J'ai un programme Delphi qui doit communiquer avec un programme écrit en C. Pour ça j'utilise le composant TIdTCPClient.

Les développeurs du programme C me donne la description des trames à lire
ex: Entete = string(7) + null
     TaillePaquet = long
     TypePaquet = long
     TailleDonnees = long
     Donnees = TailleDonnees

Jusque là tout va bien, je n'ai pas de problème pour lire Entete, TaillePaquet, TypePaquet et TailleDonnees.
Maintenant j'essaie de lire la donnée sachant qu'elle se compose comme ceci:
PosProcessItemType = integer
PosItemId = string(20) + null
PosItemQuantity = Integer
.... (pas besoin de connaître la suite car après le PosItemId j'ai un décalage)

Pour lire j'utilise les fonctions ReadInteger et ReadString du composant TIdTCPClient.
PosProcessItemType:= MonCompo.ReadInteger(False);
PosItemId:= MonCompo.ReadString(21); // 21 pour string(20) + null
PosItemQuantity:= MonCompo.ReadInteger(False);

Quand je test PosItemQuantity, il n'a pas la valeur qu'il devrait avoir selon les logs du programme C.
Après analyse de la trame avec WireShark, j'ai détécté qu'il y avait un décalage de 3 octets. Je change donc mon code en :
PosProcessItemType:= MonCompo.ReadInteger(False);

PosItemId:= MonCompo.ReadString(24);

PosItemQuantity:= MonCompo.ReadInteger(False);

Je n'ai plus le problème. Vous allez me dire que je n'ai qu'à faire comme ça mais j'ai beaucoup de trame avec des chaines et je vous ai donné le cas le plus simple, je ne peux pas passer 30 min à compter chaque octet dans les trames.
Le gars qui a fait le programme en C me certifie que c'est Delphi qui a des problèmes pour lire les structures C mais moi je n'y crois pas du tout (surtout que j'ai fait le test en C# et j'ai le même problème). Pourriez-vous m'aider et me donner vos impressions sur ce problème, ainsi que vos idées.

Je vous remercie d'avance (j'ai la tête qui va exploser avec ce truc)

 

3 réponses


Salut,

Si tu connais exactement la structure des données pourquoi ne pas utiliser un record . Pour exemple avec le composant TClientSocket (Désolé je n'ai pas Indy d'installer) :

procedure TForm1.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
Type
  TData=Record
    PosProcessItemType:Integer;
    PosItemId:string[20];
    PosItemQuantity : Integer;
   //ect ect
  End;
Var
  Data:TData;
begin
  ClientSocket1.Socket.ReceiveBuf(Data,SizeOf(Data));
end;

En ce qui concerne la difficulté qu'a Delphi de lire les structures C : tu as raison, l'explication qui t'a été donnée est vaseuse .  En effet la seule chose qui circule ce sont des bits . Sans parler du fait qu'un compilo traduit le code en Assembleur avant la compilation.

A mon avis il y a surtout un probleme au niveau de ton code. Coté serveur, il semble que cette structure soit envoyée d'un coup. Alors que de ton coté tu cherchers à récupérer les données type par type au fur et à mesure. Si c'est le cas, il est un peu normal que ca foire.
Messages postés
6
Date d'inscription
vendredi 24 avril 2009
Statut
Membre
Dernière intervention
22 juin 2009

Merci beaucoup, ça marche. Le seul petit truc où je dois faire attention dans mon record c'est de ne pas utiliser de string[x] mais plutôt des array[x..y] of Char. Tu me retires une épine du pieds. Merci encore à toi.
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
13
Bravo francky, allez, retourne bosser Tom et arrête ta sirène XD