Socket TCP et décalage d'octet

Résolu
tlelong Messages postés 6 Date d'inscription vendredi 24 avril 2009 Statut Membre Dernière intervention 22 juin 2009 - 24 avril 2009 à 16:20
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 - 27 avril 2009 à 14:27
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

Utilisateur anonyme
24 avril 2009 à 20:42
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.
3
tlelong Messages postés 6 Date d'inscription vendredi 24 avril 2009 Statut Membre Dernière intervention 22 juin 2009
27 avril 2009 à 10:24
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.
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
27 avril 2009 à 14:27
Bravo francky, allez, retourne bosser Tom et arrête ta sirène XD
0
Rejoignez-nous