OVH Cloud OVH Cloud

Socket Java et C++

22 réponses
Avatar
David Noyelle
Bonjour a tous,

j'ai 2 programmes :

- un programme en C++ qui fait office de socket d'ecoute.
- un programme Java qui se connecte a la socket du programme C++.

Jusqu'ici la connexion fonctionne bien. Une fois la connexion creee, le
programme Java demande au programme C++ de lui transmettre une structure qui
est la suivante:
--------------------------------------------
typedef struct
{
CONFIG_TRACE trace;
CONFIG_COM config_com;
WORD PORT_ECOUTE;
WORD PORT_ECOUTE_ADMIN;
WORD modbus_timeout;
WORD modbus_turnaround;
} CONFIG;
--------------------------------------------

Mais le programme Java ne recoit pas correctement cette structure (a
l'affichage ca me donne "_CONFIG") car la socket Java place le contenu de
son entree (in = socket.getInputStream()) dans une variable de type String
(inString = monProg.in.readLine()) .

Ma question est la suivante : est-ce que je dois creer une structure du cote
Java qui soit identique a la structure du cote C++ pour pouvoir la recuperer
correctement ? Ou est-ce que je peux recuperer cette structure dans un
tableau ?

Par exemple : structureJava = monProg.in.readLine()
tableauJava = monProg.in.readLine()

Je precise que la structure emise par le programme C++ est essentiellement
constituee de variable de type WORD (16 bits - short) et DWORD (32 bits -
int) .

Merci d'avance pour vos suggestions,

--
David NOYELLE
davidnoyelle chez yahoo point fr

10 réponses

1 2 3
Avatar
James Kanze
"Arnaud Debaene" writes:

|> Généralement, on utilise la convention Internet (Big Endian si je me
|> souviens bien) pour sérialiser les données, et on utilise les
|> fonctions htons, htonl, ntohs et ntohl pour passer de la convention
|> locale à la machine à la convention Internet et vice-versa. Sur une
|> machine big endian, ces fonctions ne font rien mais sur un machine
|> little endian, elles inversent l'ordre des octets de leur paramètre.

Généralement, on définit un format, et à partir de là, le flux ne
contient que des octets, et je ne sais pas s'il y a un sens de parler de
BE/LE. (Dans la mésure où un seul octet ne suffit pas pour transmettre
un int, le format va sans doute parler de l'ordre des octets. De même
que la représentation des valeurs négatives, voire des valeurs en
général -- texte, binaire...)

Et bien que je travaille sur des protocols de transmission depuis
longtemps, je ne me suis jamais servi de htons, etc. Je n'en vois pas
l'intérêt.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
Arnaud Debaene
James Kanze wrote:
"Arnaud Debaene" writes:


Généralement, on définit un format, et à partir de là, le flux ne
contient que des octets, et je ne sais pas s'il y a un sens de parler
de BE/LE. (Dans la mésure où un seul octet ne suffit pas pour
transmettre un int, le format va sans doute parler de l'ordre des
octets.
...et donc va employer les termes big endian ou little endian, d'où

l'intérêt de connaître leur signification ;-)


Et bien que je travaille sur des protocols de transmission depuis
longtemps, je ne me suis jamais servi de htons, etc. Je n'en vois pas
l'intérêt.
Tu fais les inversions des octets toi-même quand tu sérialise / désérialise

des données?

Arnaud

Avatar
jerome moliere
David Noyelle wrote:
Bonjour a tous,

j'ai 2 programmes :
<snip>

Ma question est la suivante : est-ce que je dois creer une structure du cote
Java qui soit identique a la structure du cote C++ pour pouvoir la recuperer
correctement ? Ou est-ce que je peux recuperer cette structure dans un
tableau ?
je vais peut etre pas t'arranger et proposer autre chose que tout ce qui

a ete dit mais je pense que l'approche la plus viable en terme :
de qualite logicielle
de maintenance du code
de performance
serait d'utiliser un dialogue regi par CORBA...
avec 2 ORBs de ton choix (cela ne manque pas)
tu ecriras en effet une IDL avec tes services et les structs devant
vehiculer sur le reseau (ta structure STRUCT !!) mais tu ne t'occuperas
pas de la plomberie :) et tu feras de l'objet...
car personne n'a parle de la montee en charge mais elle me parait plus
simple a gerer avec une Policy adequate au niveau du POA de ton ORB qu'a
coder a la mimine....

my 2 pieces
jerome

--
Auteur cahier du programmeur Java tome 2 - Eyrolles 10/2003
http://www.eyrolles.com/php.informatique/Ouvrages/ouvrage.php3?ouv_ean13—82212111941

Avatar
kanze
"Arnaud Debaene" wrote in message
news:<411fe563$0$29673$...
James Kanze wrote:
"Arnaud Debaene" writes:

Généralement, on définit un format, et à partir de là, le flux ne
contient que des octets, et je ne sais pas s'il y a un sens de
parler de BE/LE. (Dans la mésure où un seul octet ne suffit pas pour
transmettre un int, le format va sans doute parler de l'ordre des
octets.


...et donc va employer les termes big endian ou little endian, d'où
l'intérêt de connaître leur signification ;-)


Éventuellement. Mais la signification dans un protocol n'est pas tout à
fait identique que quand on parle de la mémoire.

Et bien que je travaille sur des protocols de transmission depuis
longtemps, je ne me suis jamais servi de htons, etc. Je n'en vois
pas l'intérêt.


Tu fais les inversions des octets toi-même quand tu sérialise /
désérialise des données?


Quelles inversions ? Si le protocol démande de transmettre un entier en
quatre octets, complément à deux, octet de poids fort d'abord, j'écris
du code pour mettre d'abord les bits 24-31, puis les bits 16-23, etc.
d'un int :

obstream&
operator<<( obstream& dest, int value )
{
obstream::sentry s( dest ) ;
if ( s ) {
unsigned tmp = value ;
streambuf* sb = dest.rdbuf() ;
int shift = 32 ;
while ( tmp && shift > 0 ) {
shift -= 8 ;
if ( sb->sputc( (tmp >> shift) & 0xff ) == EOF ) {
dest.setstate( std::ios::badbit ) ;
}
}
}
return dest ;
}

Ça marche sur toutes les machines où la taille d'un int est au moins 32
bits. Indépendamment de comment les int sont représentés dans la
machine.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
"Arnaud Debaene" wrote in message
news:<411c8a03$0$18615$...
Michaël Delva wrote:
Pour les détails, comme le problème BE/LE, je laisse d'autres
contributeurs te renseigner.





[encore plus de détails... les reseaux et les protocols, c'est mon
domaine de prédélection]

Qu'est-ce que c'est que ces problèmes de BE/LE? J'en ai déjà entendu
parler, mais je ne sais pas ce que c'est?


Big Endian / Littel Endian. Un nombre représenté sur plusieurs octets
peut l'être de 2 façons : soit avec l'octet de poids faible à
l'adresse la plus basse (little endian), soit avec l'octet de poids
fort à l'adresse la plus basse (big endian).


En fait, un nombre représenté sur quatre octets peut l'être 24 façons,
dont au moins trois ont réelement servi (sur des systèmes où j'ai
travaillé). Et ça, c'est sans prendre en compte la représentation des
négatifs (complément à deux, complément à un, magnitude et signe -- tous
les trois réelement utilisés) ni la présense éventuelle des bits de
rembourrage non utilisés.

Différents processeurs utilisent l'une ou l'autre de ces conventions.


Ou un troisième. Ou quelque chose de complètement différent.

Si des machines avec des processeurs différents communiquent entre
elles, il faut en tenir compte.


Dès que tu sort du processus, il faut définir un format.

En fait, l'utilisation des expressions Big Endian et Little Endian ont
commencé dans la description des protocols -- où on transmet des bits,
et non des octets. Ils peuvent donc référer aussi bien à l'ordre des
bits dans un octet qu'à l'ordre des octets dans un mot. (En fait, dans
tous les protocols que je connais, l'ordre des bits est little endian.
Sans doute parce que la sérialisation des bits se fait prèsque toujours
en hardware, le premier protocol était LE, et les protocols suivants ont
voulu utiliser le même hardware.)

Généralement, on utilise la convention Internet (Big Endian si je me
souviens bien) pour sérialiser les données,


L'Internet, c'est varié. En général, c'est LE au niveau des bits. Les
protocols de bas niveau (IP, UDP, TCP) utilisent en général des entiers
à deux ou (plus souvent) à quatres octets binaire, complément à deux,
l'octet de poids fort d'abord. Mais il leur arrive aussi de caser un
nombre en moins d'un octet. Et chaque couche applicative est libre -- la
plus répandu, c'est probablement une représentation textuelle (SMTP,
HTTP, etc.), mais ce n'est pas exclusif. Pour les représentations
binaires à longueur fixe, c'est encore complément à deux, poids fort
d'abord qui prédomine, mais pour les représentations binaire à longueur
variable (certains champs en BER, par exemple), poids faible d'abord est
probablement plus fréquent.

Au niveau de la programmation, on a une valeur entière, et un format à
respecter. Et c'est vraiment rare d'aller plus loin et de s'intéresser
en comment est représenter cette valeur dans la machine sur laquelle on
tourne. C++ a des opérateurs qu'il faut pour extraire des bits qui nous
intéressent de la valeur. Encore plus intéressant, C++ a des opérations
qu'il faut pour obtenir des bits qui correspond à une représentation
complément à deux, quelque soit la représentation utilisée par le
hardware -- regarde bien la sémantique des conversions signed vers
unsigned.

et on utilise les fonctions htons, htonl, ntohs et ntohl pour passer
de la convention locale à la machine à la convention Internet et
vice-versa.


Fonctions qui ne sont pas présentes sur toutes les implémentations C++.
Et qui n'ont de sens que si la machine a des entiers de la même taille
et qui utilisent la même représentation qu'on veut. Choses qu'il est
difficile à garantir.

Sur une machine big endian, ces fonctions ne font rien mais sur un
machine little endian, elles inversent l'ordre des octets de leur
paramètre.


C'est un hack. Un modèle de mauvaise conception. Pour un exemple concret
d'une solution portable, voir mon autre posting, mais en général, pour
sortir un entier, l'algorithme est :

- vérifier que la valeur en entrée peut être représentée dans le
format prévu,

- l'affecter à un unsigned d'une grandeur suffisante, pour s'assurer
d'une conversion en complément à deux, et

- extraire les bits qu'il faut, au moyen des décalages et des
masquages, pour les mettre où il faut (ce qui pourrait
éventuellement aussi impliquer des décalages et des masquages).

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34




Avatar
drkm
writes:

"Arnaud Debaene" wrote in message
news:<411c8a03$0$18615$...

Michaël Delva wrote:

Pour les détails, comme le problème BE/LE, je laisse d'autres
contributeurs te renseigner.





[encore plus de détails... les reseaux et les protocols, c'est mon
domaine de prédélection]


C'est bien à toi que je pensais (entre autres) ;-)

[...]

Encore plus intéressant, C++ a des opérations
qu'il faut pour obtenir des bits qui correspond à une représentation
complément à deux, quelque soit la représentation utilisée par le
hardware -- regarde bien la sémantique des conversions signed vers
unsigned.


Tu veux dire que la norme parle de la représentation en complément à
deux ? Mais je ne comprend pas pourquoi tu parles de conversions. À
part spécifier la représentation des entiers signés, je ne vois pas
pourquoi elle en parlerait. Et je trouverais bizarre qu'elle impose
la représentation des entiers signés.

Qu'en est-il, exactement ? Je ne peux malheureusement pas accéder à
ma copie de la norme, actuellement.

et on utilise les fonctions htons, htonl, ntohs et ntohl pour passer
de la convention locale à la machine à la convention Internet et
vice-versa.


Fonctions qui ne sont pas présentes sur toutes les implémentations C++.


Bof. S'il s'occupe de transmissions réseaux ...

[...]

PS: fu2 f.c.l.c++

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html





Avatar
drkm
writes:

Ça marche sur toutes les machines où la taille d'un int est au moins 32
bits. Indépendamment de comment les int sont représentés dans la
machine.


Sauf si l'entier est sur plus de 32 bits, et que la valeur ne tient
pas sur les 32 bits. Je me demande alors : est-ce la responsabilité
du flux (d'après la philisophie des IOStreams standards) de vérifier
cela, ou serait-ce plutôt une précondition ?

PS: fu2 f.c.l.c++

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Avatar
kanze
drkm wrote in message
news:...

writes:

Ça marche sur toutes les machines où la taille d'un int est au moins
32 bits. Indépendamment de comment les int sont représentés dans la
machine.


Sauf si l'entier est sur plus de 32 bits, et que la valeur ne tient
pas sur les 32 bits. Je me demande alors : est-ce la responsabilité du
flux (d'après la philisophie des IOStreams standards) de vérifier
cela, ou serait-ce plutôt une précondition ?


C'est une précondition. Au quel niveau, je ne sais pas.

C'est en tout cas la responsibilité du flux à le vérifier. Si c'est
vraiment une précondition dans le sens de la programmation par contrat,
alors, il le vérifie avec un assert, ou quelque chose de semblable. Si
c'est une précondition au sens lache du mot, mais pas au sens de la
programmation par contrat, il vérifie, et positionne un bit d'erreur
dans le flux. (Mais j'aurais tendance à priviliger l'assert.)

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
drkm wrote in message
news:...

writes:


[...]
Encore plus intéressant, C++ a des opérations
qu'il faut pour obtenir des bits qui correspond à une représentation
complément à deux, quelque soit la représentation utilisée par le
hardware -- regarde bien la sémantique des conversions signed vers
unsigned.


Tu veux dire que la norme parle de la représentation en complément à
deux ?


La norme précise la valeur qui en résult quand on convertit une valeur
négative en type non-signé. Par hazard ;-), les bits, c'est exactement
des bits qu'on aurait avec complément à deux. (C-à-d que sur une machine
complément à deux, la conversion d'un type signé en type non-signé ne
doit changer aucun bit. Tandis que sur les autres machines, il faut que
les bits changent.)

Mais je ne comprend pas pourquoi tu parles de conversions.


Parce que c'est à travers la conversion signé vers non-signé qu'on
obtient les bits qui correspondent à une représentation à complément à
deux.

Prenons un cas simple, avec des char's de 8 bits. La norme exige dans ce
cas-ci que UCHAR_MAX est 255 (c-à-d 0xFF, tous les bits à un). En ce qui
concerne la représentation de -1 dans un signed char, elle est ouverte :
on peut avoir 0xFF, 0xFE ou 0X81. Seulement, quand j'affecte ce -1 à un
unsigned char, quelque soit la représentation, la norme dit que
j'obtient 255, et que la représentation de 255, c'est bien 0xFF.

À part spécifier la représentation des entiers signés, je ne vois pas
pourquoi elle en parlerait. Et je trouverais bizarre qu'elle impose la
représentation des entiers signés.


Elle n'impose pas de représentation des entiers signés (à part qu'elle
soit binaire). Elle définit en revanche le résultat de la conversion
d'une valeur négative en type non-signé, et elle le définit de façon à
ce que la représentation du résultat correspond à la représentation de
la valeur initiale en complément à deux.

Qu'en est-il, exactement ? Je ne peux malheureusement pas accéder à
ma copie de la norme, actuellement.


Voir ci-dessus.

et on utilise les fonctions htons, htonl, ntohs et ntohl pour
passer de la convention locale à la machine à la convention
Internet et vice-versa.


Fonctions qui ne sont pas présentes sur toutes les implémentations C++.


Bof. S'il s'occupe de transmissions réseaux ...


Je ne sais pas. Est-ce qu'elles sont présentent sous Windows ? Est-ce
qu'elles sont même présentes sur tous les Unix -- je ne les trouve pas
dans la norme Posix ?

Et comme j'ai dit, je n'en ai pas encore trouvé une utilité, bien que
j'ai fait beaucoup de réseau.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
kanze
drkm wrote in message
news:...

writes:


[...]
Encore plus intéressant, C++ a des opérations
qu'il faut pour obtenir des bits qui correspond à une représentation
complément à deux, quelque soit la représentation utilisée par le
hardware -- regarde bien la sémantique des conversions signed vers
unsigned.


Tu veux dire que la norme parle de la représentation en complément à
deux ?


La norme précise la valeur qui en résult quand on convertit une valeur
négative en type non-signé. Par hazard ;-), les bits, c'est exactement
des bits qu'on aurait avec complément à deux. (C-à-d que sur une machine
complément à deux, la conversion d'un type signé en type non-signé ne
doit changer aucun bit. Tandis que sur les autres machines, il faut que
les bits changent.)

Mais je ne comprend pas pourquoi tu parles de conversions.


Parce que c'est à travers la conversion signé vers non-signé qu'on
obtient les bits qui correspondent à une représentation à complément à
deux.

Prenons un cas simple, avec des char's de 8 bits. La norme exige dans ce
cas-ci que UCHAR_MAX est 255 (c-à-d 0xFF, tous les bits à un). En ce qui
concerne la représentation de -1 dans un signed char, elle est ouverte :
on peut avoir 0xFF, 0xFE ou 0X81. Seulement, quand j'affecte ce -1 à un
unsigned char, quelque soit la représentation, la norme dit que
j'obtient 255, et que la représentation de 255, c'est bien 0xFF.

À part spécifier la représentation des entiers signés, je ne vois pas
pourquoi elle en parlerait. Et je trouverais bizarre qu'elle impose la
représentation des entiers signés.


Elle n'impose pas de représentation des entiers signés (à part qu'elle
soit binaire). Elle définit en revanche le résultat de la conversion
d'une valeur négative en type non-signé, et elle le définit de façon à
ce que la représentation du résultat correspond à la représentation de
la valeur initiale en complément à deux.

Qu'en est-il, exactement ? Je ne peux malheureusement pas accéder à
ma copie de la norme, actuellement.


Voir ci-dessus.

et on utilise les fonctions htons, htonl, ntohs et ntohl pour
passer de la convention locale à la machine à la convention
Internet et vice-versa.


Fonctions qui ne sont pas présentes sur toutes les implémentations C++.


Bof. S'il s'occupe de transmissions réseaux ...


Je ne sais pas. Est-ce qu'elles sont présentent sous Windows ? Est-ce
qu'elles sont même présentes sur tous les Unix -- je ne les trouve pas
dans la norme Posix ?

Et comme j'ai dit, je n'en ai pas encore trouvé une utilité, bien que
j'ai fait beaucoup de réseau.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



1 2 3