/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Konvetering af Long
Fra : jsi


Dato : 25-04-02 16:12

Jeg har en unsigned Long som jeg skal have sendt over en winsock
forbindelse og derfor skal den castes/konveteres til et char array.
Og i modsatte ende af socketforbindelsen skal jeg så igen har castet
den tilbage til en Long..

Nogle forslag til hvordan jeg gør dette??

Eller andre bedre ideer til hvordan jeg får sendt en long over en
winsock2 forbindelse??

På forhånd tak


/Jakob

 
 
Mogens Hansen (25-04-2002)
Kommentar
Fra : Mogens Hansen


Dato : 25-04-02 17:17


"jsi" <jsi@mail.ikasths.dk> wrote in message
news:3cc819f9.10459519@news.uni-c.dk...
> Jeg har en unsigned Long som jeg skal have sendt over en winsock
> forbindelse og derfor skal den castes/konveteres til et char array.
> Og i modsatte ende af socketforbindelsen skal jeg så igen har castet
> den tilbage til en Long..
>
> Nogle forslag til hvordan jeg gør dette??
>

Du må _ikke_ caste, for der er ikke nogen _garanti_ for at det vil virke
pga. alignment (selvom det sikkert vil).
Brug i stedet memcpy (jeg har ikke compileret det)

Send:
long value = 7L;
char buffer[sizeof(long)];
memcpy(buffer, &value, sizeof(long));
send nu indholdet af bufferen.

Modtag
char buffer[sizeof(long)]; // has content !!!
long value;
memcpy(&value, buffer, sizeof(long));
brug nu value.

Vær opmærksom på at det kan give problemer, med little-endian / big-endian,
hvis der sendes mellem forskellige CPU arkitekturer.

> Eller andre bedre ideer til hvordan jeg får sendt en long over en
> winsock2 forbindelse??
>

Brug eventuelt et bibliotek som ACE, der dels indkapsler
platformsafhængigheder, øger type sikkerheden og som har funktionalitet til
at sikre at f.eks. en long bliver sendt rigtigt, også på tværs af CPU
arkitekturer.
Se f.eks. bogen
C++ Network Programming: Mastering Complexity Using ACE and Patterns
ISBN 0-201-60464-7
Douglas C. Schmidt
Stephen D. Huston
eller http://www.cs.wustl.edu/~schmidt/ACE.html


Venlig hilsen

Mogens Hansen



Thomas Krog (25-04-2002)
Kommentar
Fra : Thomas Krog


Dato : 25-04-02 17:40

> Du må _ikke_ caste, for der er ikke nogen _garanti_ for at det vil virke
> pga. alignment (selvom det sikkert vil).

Jeg forstår ikke hvorfor nedenstående kan gå galt mens din metode med memcpy
virker (svjv. tager memcpy ikke højde for hvilke typer der bruges og burde
derfor ikke kunne hjælpe hvis der bruges forskellig alignment hos afsender
og modtager):

long value = 7L;
sendWithWinSock((const char*)&value,sizeof(long));



Mogens Hansen (25-04-2002)
Kommentar
Fra : Mogens Hansen


Dato : 25-04-02 21:41


"Thomas Krog" <rick@kampsax.dtu.dk> wrote

> > Du må _ikke_ caste, for der er ikke nogen _garanti_ for at det vil virke
> > pga. alignment (selvom det sikkert vil).
>
> Jeg forstår ikke hvorfor nedenstående kan gå galt mens din metode med
memcpy
> virker (svjv. tager memcpy ikke højde for hvilke typer der bruges og burde
> derfor ikke kunne hjælpe hvis der bruges forskellig alignment hos afsender
> og modtager):
>
> long value = 7L;
> sendWithWinSock((const char*)&value,sizeof(long));
>

Du har formodentlig ret i at det kan sendes på den måde.
Jeg brugte "memcpy" i afsendelsen, fordi man ofte vil sende mere end een
værdi i en pakke, og derfor serieliserer man dem ned i en buffer før
afsendelsen.
Det jeg (ikke tydeligt nok) advarede imod, var at anvende læsebufferen
direkte til at bruge værdierne via cast (sådan som Bertel Lund Hansen har
foreslået i denne tråd). Det er nærliggende og fristende - men det er blot
ikke garanteret at det virker, og kan give overraskelser senere. Jeg har set
bus-error af den grund. Se desuden mit svar til Bertel Lund Hansen.

Venlig hilsen

Mogens Hansen



Byrial Jensen (26-04-2002)
Kommentar
Fra : Byrial Jensen


Dato : 26-04-02 09:41

Thomas Krog <rick@kampsax.dtu.dk> skrev:
>> Du må _ikke_ caste, for der er ikke nogen _garanti_ for at det vil virke
>> pga. alignment (selvom det sikkert vil).
>
> Jeg forstår ikke hvorfor nedenstående kan gå galt
>
> long value = 7L;
> sendWithWinSock((const char*)&value,sizeof(long));

Det kan det heller ikke, så vidt jeg kan se. Da ethvert objekt
altid vil fylde et helt antal char (da sizeof(char) er 1), må en
pointer til et objekt nødvendigvis altid være korrekt alignet til
char.

C99 siger da også (bemærk specielt de 2 sidste punktummer):

[#7] A pointer to an object or incomplete type may be
converted to a pointer to a different object or incomplete
type. If the resulting pointer is not correctly aligned57)
for the pointed-to type, the behavior is undefined. Otherwise,
when converted back again, the result shall compare equal to
the original pointer. When a pointer to an object is
converted to a pointer to a character type, the result points
to the lowest addressed byte of the object. Successive
increments of the result, up to the size of the object, yield
pointers to the remaining bytes of the object.

Mogens Hansen tænkte nok på konvertering den anden vej hvor
nedenstående metode /ikke/ kan bruges:

char buffer[sizeof(long)];
long value;
/* ... */
rc = fread (buffer, 1, sizeof(buffer), stream);
/* ... */
value = *(long *)buffer; /* Fejl - buffer er ikke nødvendigvis
alignet som krævet for type long */

Thomas Krog (26-04-2002)
Kommentar
Fra : Thomas Krog


Dato : 26-04-02 14:09

> Mogens Hansen tænkte nok på konvertering den anden vej hvor
> nedenstående metode /ikke/ kan bruges:
>
> char buffer[sizeof(long)];
> long value;
> /* ... */
> rc = fread (buffer, 1, sizeof(buffer), stream);
> /* ... */
> value = *(long *)buffer; /* Fejl - buffer er ikke nødvendigvis
> alignet som krævet for type long */

man burde dog også kunne gøre sådan:

long value;
reciveFromWinSock((char*)&value,sizeof(long));

så det er kun hvis der skal overføres forskellige typer på een gang at det
er nødvendigt at lave en ekstra kopi til/fra en char buffer.



jsi (25-04-2002)
Kommentar
Fra : jsi


Dato : 25-04-02 18:26

On Thu, 25 Apr 2002 18:17:01 +0200, "Mogens Hansen"
<mogens_h@dk-online.dk> wrote:

>
>"jsi" <jsi@mail.ikasths.dk> wrote in message
>news:3cc819f9.10459519@news.uni-c.dk...
>> Jeg har en unsigned Long som jeg skal have sendt over en winsock
>> forbindelse og derfor skal den castes/konveteres til et char array.
>> Og i modsatte ende af socketforbindelsen skal jeg så igen har castet
>> den tilbage til en Long..
>>
>> Nogle forslag til hvordan jeg gør dette??
>>
>
>Du må _ikke_ caste, for der er ikke nogen _garanti_ for at det vil virke
>pga. alignment (selvom det sikkert vil).
>Brug i stedet memcpy (jeg har ikke compileret det)
>
>Send:
> long value = 7L;
> char buffer[sizeof(long)];
> memcpy(buffer, &value, sizeof(long));
>send nu indholdet af bufferen.
>
>Modtag
> char buffer[sizeof(long)]; // has content !!!
> long value;
> memcpy(&value, buffer, sizeof(long));
>brug nu value.
>
>Vær opmærksom på at det kan give problemer, med little-endian / big-endian,
>hvis der sendes mellem forskellige CPU arkitekturer.
>
>> Eller andre bedre ideer til hvordan jeg får sendt en long over en
>> winsock2 forbindelse??
>>
>
>Brug eventuelt et bibliotek som ACE, der dels indkapsler
>platformsafhængigheder, øger type sikkerheden og som har funktionalitet til
>at sikre at f.eks. en long bliver sendt rigtigt, også på tværs af CPU
>arkitekturer.
>Se f.eks. bogen
> C++ Network Programming: Mastering Complexity Using ACE and Patterns
> ISBN 0-201-60464-7
> Douglas C. Schmidt
> Stephen D. Huston
>eller http://www.cs.wustl.edu/~schmidt/ACE.html
>
>
>Venlig hilsen
>
>Mogens Hansen
>
>


Mange tak for hjælpen som faktisk løste mit problem..

venlig hilsen
Jakob

Byrial Jensen (26-04-2002)
Kommentar
Fra : Byrial Jensen


Dato : 26-04-02 09:41

Mogens Hansen <mogens_h@dk-online.dk> skrev:

> Send:
> long value = 7L;
> char buffer[sizeof(long)];
> memcpy(buffer, &value, sizeof(long));
> send nu indholdet af bufferen.
>
> Modtag
> char buffer[sizeof(long)]; // has content !!!
> long value;
> memcpy(&value, buffer, sizeof(long));
> brug nu value.
>
> Vær opmærksom på at det kan give problemer, med little-endian / big-endian,
> hvis der sendes mellem forskellige CPU arkitekturer.

Hvis der sendes mellem forskellige arkitekturer, skal man selvfølgelig
også være opmærksom på at størrelsen af long kan være forskellig.

Bertel Lund Hansen (25-04-2002)
Kommentar
Fra : Bertel Lund Hansen


Dato : 25-04-02 17:22

jsi skrev:

>Jeg har en unsigned Long som jeg skal have sendt over en winsock
>forbindelse og derfor skal den castes/konveteres til et char array.

char sendbuf[sizeof(long)];
long *fidus;

int main () {
   fidus=(long*) sendbuf;
   *fidus=3.1415926;
   ...
}

--
Bertel
http://lundhansen.dk/bertel/   FIDUSO: http://fiduso.dk/

Mogens Hansen (25-04-2002)
Kommentar
Fra : Mogens Hansen


Dato : 25-04-02 21:39


"Bertel Lund Hansen" <nospam@lundhansen.dk> wrote

>
> char sendbuf[sizeof(long)];
> long *fidus;
>
> int main () {
> fidus=(long*) sendbuf;
> *fidus=3.1415926;

Hvilken _garanti_ har du for at "sendbuf" er alignet på en grænse, der er
compatibel med CPU'en krav til alignment af en long ? (hint: ingen).

"sendbuf" kan ligger på en ulige adresse, og CPU'en kan kræve at en long
skal starte på en lige adresse.
Afhængig af CPU arkitektur, vil der ske noget fra at det virker, over at det
går langsommere, til at CPU'en f.eks. genererer og bus-error og derefter
stopper.
Hvis en long er 32 bit og CPU'en har en 8 bit bus, skal der under alle
omstændigheder udføres 4 bus transaktioner for at overføre end long.
Hvis en long er 32 bit og CPU'en har en 32 bit bus, skal der udføres 1 bus
transaktion for at overføre en long - såfremt den er alignet på en 4 byte
grænse. Hvis den ikke er alignet på en 4 byte grænse, skal der enten udføres
2 bus transaktioner som CPU'en så stykker sammen, eller CPU'en kan nægte at
gøre det.

Det er compilerens opgave at sikre at en long er lagt ud på en måde der er
compatibel med CPU'en krav.

Se eventuelt §3.9,2 i C++ Standarden.

Venlig hilsen

Mogens Hansen



Anders Borum (25-04-2002)
Kommentar
Fra : Anders Borum


Dato : 25-04-02 23:30

"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:aa9phf$v1t$1@news.cybercity.dk...
[]
> Hvilken _garanti_ har du for at "sendbuf" er alignet på en grænse, der er
> compatibel med CPU'en krav til alignment af en long ? (hint: ingen).

Alignment af data er ikke eneste problem.

Da denne long-værdi skal sendes over en socket-forbindelse
er det ikke sikkert at det er samme maskine der skriver og
læser værdien. Det er heller ikke sikkert at afsender og
modtager er enige om hvorledes long-værdier skal gemmes.
Den ene maskine kunne være en PC og den anden en Mac.

Derfor kan det betale sig eksplicit at sige hvordan din
long skal gemmes på overfarten. Her er en mulighed.

// afsende
long data = 12345678;
unsigned char cc[4] = {data >> 24, (data >> 16) & 255,
(data >> 8) & 255, data & 255)};
send(sd, cc, 4, 0);

// modtage
unsigned char dd[4];
recv(sd, dd, 4, 0); // husker ikke helt argumenterne til recv-socket..
long genskabt_data = ((unsigned)dd[0] << 24) |
((unsigned)dd[1] << 16) |
((unsigned)dd[2] << 8) |
dd[3];

Hilsen Anders

[klip]



Anders Borum (26-04-2002)
Kommentar
Fra : Anders Borum


Dato : 26-04-02 00:32

"Anders Borum" <overflade@fedt.dk> skrev i en meddelelse news:_t%x8.3177
[klip]

Ja ok - havde jeg læst de andre meddelelser i tråden lidt
grundigere havde jeg nok ikke skrevet det forrige indlæg.

Jeg undskylder.



Lars Kringelbach (26-04-2002)
Kommentar
Fra : Lars Kringelbach


Dato : 26-04-02 10:39

> Alignment af data er ikke eneste problem.
>
> Da denne long-værdi skal sendes over en socket-forbindelse er det ikke
> sikkert at det er samme maskine der skriver og læser værdien. Det er
> heller ikke sikkert at afsender og modtager er enige om hvorledes
> long-værdier skal gemmes. Den ene maskine kunne være en PC og den anden
> en Mac.
>
> Derfor kan det betale sig eksplicit at sige hvordan din long skal gemmes
> på overfarten. Her er en mulighed.
>
> // afsende
> long data = 12345678;
> unsigned char cc[4] = {data >> 24, (data >> 16) & 255,
> (data >> 8) & 255, data & 255)};
> send(sd, cc, 4, 0);
>
> // modtage
> unsigned char dd[4];
> recv(sd, dd, 4, 0); // husker ikke helt argumenterne til recv-socket..
> long genskabt_data = ((unsigned)dd[0] << 24) |
> ((unsigned)dd[1] << 16) |
> ((unsigned)dd[2] << 8) |
> dd[3];
>
> Hilsen Anders
>
> [klip]

Hvad med at se på ntohl(long) (network-to-host-long) og htonl(long)
(host-to-network-long). De konverterer mellem en fast standard for
byte-order på netværket til den lokale standard på host'en og omvendt. Det
løser i hvert fald problemet med little-endian og big-endian.

Mvh Lars

Anders Borum (28-04-2002)
Kommentar
Fra : Anders Borum


Dato : 28-04-02 20:25

"Lars Kringelbach" <lars@kringelbach.com> skrev i en meddelelse
news:pan.2002.04.26.11.38.51.838132.736@kringelbach.com...
[klip]
> Hvad med at se på ntohl(long) (network-to-host-long) og htonl(long)
> (host-to-network-long). De konverterer mellem en fast standard for
> byte-order på netværket til den lokale standard på host'en og omvendt. Det
> løser i hvert fald problemet med little-endian og big-endian.

Jeg tænkte det var mere illustrativt at vise hvordan konverteringen
kunne foregå på laveste niveau.

Det er selvfølgelig mere effektivt at kalde de indbyggede funktioner
eftersom de ingenting laver i tilfældet at netværks-rækkefølge og
maskin-rækkefølge er ens.



Byrial Jensen (26-04-2002)
Kommentar
Fra : Byrial Jensen


Dato : 26-04-02 09:41

Bertel Lund Hansen <nospam@lundhansen.dk> skrev:
> char sendbuf[sizeof(long)];
> long *fidus;
>
> int main () {
>    fidus=(long*) sendbuf;
>    *fidus=3.1415926;
>    ...
> }

En meget dårlig fidus. Der er nemlig ikke nogen garanti for at den
virker pga. alignmentfejl.

Søg
Reklame
Statistik
Spørgsmål : 177500
Tips : 31968
Nyheder : 719565
Indlæg : 6408514
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste