Click to See Complete Forum and Search --> : Byte Ordering


Maninder
November 23rd, 2001, 02:36 AM
Hello,
I had made an application which prepares a byte stream and sends it to other machine on TCP/IP.I made it on SUN Netra machine and the other machine is also on sun netra.
When I recompile the same code on Compaq Dec Alpha machine the same message is not in the right order.

message on SUN
0000 0024 0000 0002 0000 0000 0000 0001
3132 3334 3500 7061 7373 0056 4d43 5749
0033 0000

message on Compaq

2400 0000 0200 0000 0000 0000 0100 0000
3132 3334 3500 7061 7373 0056 4d43 5749
0033 0000


Any suggestions......

the relevant code for preparation of bytestream is

int len=36, cmdid=2, cmdstat=0, seqNum=0;
int smpver=0x33;

sendmsg=(char *)malloc(len);
memcpy(sendmsg,(void*)&len,4);
memcpy(sendmsg+4,(void*)&cmdId,4);
memcpy(sendmsg+8,(void*)&cmdStat,4);
memcpy(sendmsg+12,(void*)&seqNum,4);
memcpy(sendmsg+16,(void*)argv[3],strlen(argv[3])+1);
memcpy(sendmsg+16+strlen(argv[3])+1,(void*)argv[4],strlen(argv[4])+1);
memcpy(sendmsg+16+strlen(argv[3])+1+strlen(argv[4])+1,(void*)argv[5],strlen(argv[5])+1);
memcpy(sendmsg+16+strlen(argv[3])+1+strlen(argv[4])+1+strlen(argv[5])+1,(void*)&smpver,1);
memcpy(sendmsg+16+strlen(argv[3])+1+strlen(argv[4])+1+strlen(argv[5])+1+1,(void*)&null,1);
memcpy(sendmsg+16+strlen(argv[3])+1+strlen(argv[4])+1+strlen(argv[5])+1+1+1,(void*)&null,1);
memcpy(sendmsg+16+strlen(argv[3])+1+strlen(argv[4])+1+strlen(argv[5])+1+1+1+1,(void*)&null,1);

Igor Soukhov
November 23rd, 2001, 02:58 AM
There was an article on "C/C++ Users Journal" on this problem - so have a look at it:
http://cuj.com/articles/2001/0110/0110a/0110a.htm?topic=articles


Please - rate answer if it helped you
It gives me inspiration when I see myself in the top list =)

Best regards,

-----------
Igor Soukhov (Brainbench/Tekmetrics ID:50759)
igor@soukhov.com | ICQ:57404554 | http://soukhov.com

Russian Software Developer Network http://rsdn.ru

Lee Peart
November 27th, 2001, 11:24 AM
Firstly, to answer your immediate question, to avoid problems with byte order you should do the following...

1. Declare you're variables as long values. The reason for this is that it is not guaranteed an integer will be four bytes, it might be only two. long on the other hand is always going to be four bytes.

2. When sending long values use htonl() to convert the byte order to a standard. At the receiving end you use ntohl() to set the byte order correctly for that machine.

htonl() converts the byte order of a long value from whatever the host machine uses to network byte order(known as big-endian). Inversely ntohl() will convert from network byte order to whatever the host machine uses.


A couple of other points about your code which you may want to look at - I do this to help, not offend...

1. You allocate 36 bytes for your data packet but actually write 37. It adds up as...
len : 4 bytes
cmdId : 4 bytes
cmdStat : 4 bytes
seqNum : 4 bytes
argv[3] : 6 bytes ("12345" + null)
argv[4] : 5 bytes ("pass" + null)
argv[5] : 6 bytes ("VMCWI" + null)
smpver : 1 byte (??? I'll come back to this shortly)
null : 1 byte
null : 1 byte
null : 1 byte
TOTAL : 37 bytes


You have not made any checks that the data you are storing is within the limits of the byte array. This could cause all kinds of problems such as segmentation faults or some other data item being overwritten with garbage. Your program should be more robust.

2. Getting back to the way you handle smpver. You declare this as an int (2 or 4 bytes as already mentioned) but then write it into the byte array as only one byte. If you want to insert a single byte at this point then define smpver as an unsigned char. The way you have done it has unpredictable results - although it looks as though you got away with it this time.

3. Try to make your code simpler to read, and easier to debug. You should consider using a variable to store the current position in the byte array, rather than having a larger and larger sum on each line of code. Try something like this...

long len;
long cmdId = 2;
long cmdStat = 0;
long seqNum = 0;
// Add variable to keep place in byte array
int count = 0;
unsigned char smpVer = 0x33;
// Calculate correct length of byte array
// 4+4+4+4+strlen(argv[3])+1+strlen(argv[4])+1+strlen(argv[5])+1+1+1+1+1;
len = 23 + strlen(argv[3]) + strlen(argv[4]) + strlen(argv[5]);
// If 36 bytes is maximum length then you need to check data fits ...
// else allocate the required number of bytes
sendMsg = (char*)malloc(len);
// Set all bytes to zero to start with - saves copying nulls
memset(sendMsg, 0, len);
// Convert all long values to network byte order
len = htonl(len);
cmdId = htonl(cmdId);
cmdStat = htonl(cmdStat);
seqNum = htonl(seqNum);
// Copy data to byte array
memcpy(sendMsg + count, (void*)&len, 4);
count += 4;
memcpy(sendMsg + count, (void*)&cmdId, 4);
count += 4;
memcpy(sendMsg + count, (void*)&cmdStat, 4);
count += 4;
memcpy(sendMsg + count, (void*)&seqNum, 4);
count += 4;
memcpy(sendMsg + count, (void*)argv[3], strlen(argv[3]));
count += strlen(argv[3]) + 1;
memcpy(sendMsg + count, (void*)argv[4], strlen(argv[4]));
count += strlen(argv[4]) + 1;
memcpy(sendMsg + count, (void*)argv[5], strlen(argv[5]));
count += strlen(argv[5]) + 1;
memcpy(sendMsg + count, (void*)&smpVer, 1);




There are other ways to tighten up the code but I think that is enough to be going on with.


Relax and Enjoy!!!

P.S. You would be amazed at how few people have the common decency to say if an answer helped (or not).