3

I am relatively new to C-programming and have found no answer yet. I want to send and receive integers, chars and longs as bytes over a TCP connection correctly. I have built this, but it doesn't work yet.

Sender:

int a = 12345;
char b = -1;
unsigned long c = 12174723939;
unsigned char array[256];


array[0] = (a >> 0) & 0xFF;
array[1] = (a >> 8) & 0xFF;
array[2] = (b >> 16) & 0xFF;  //Is this correct for -1?
array[3] = (c >> 24) & 0xFF;
array[4] = (c >> 32) & 0xFF;
array[5] = (c >> 40) & 0xFF;
array[6] = (c >> 48) & 0xFF;

send(socket, array, sizeof(array),0);  //or is &array better?

Receiver:

int a;
char b;
unsigned long c;
unsigned char array[256];

recv(socket, array, sizeof(array),0);

a |= (array[0] << 0) & 0xFF;
a |= (array[1] << 8) & 0xFF;
b |= (array[2] << 16) & 0xFF;
c |= (array[3] << 24) & 0xFF;
c |= (array[4] << 32) & 0xFF;
c |= (array[5] << 40) & 0xFF;
c |= (array[6] << 48) & 0xFF;

Is this correct? What is missing? Is there any other solution?

How is it done with the receiving part? I've read about big and little endians (with htonl/htons and ntohl/ntosl). Does someone have an example on how to implement it, for example, in this code?

9
  • When running server and client on the same box, endianess is not an issue be definition. Commented Oct 28, 2016 at 14:44
  • @alk but design your software for future use is always well invested time. The step between "on same box" to "distributed version" is very short... Commented Oct 28, 2016 at 14:47
  • @LPs: I completely agree. I just wanted to hint, that "it doesn't work" might not be related to endianess. Commented Oct 28, 2016 at 14:49
  • You want to search for "marshalling" or "serialization". Commented Oct 28, 2016 at 14:50
  • 1
    in the Receiver you'll need to initialize a, b, c to 0, or change the first line of their respective assignments to (for example) a = (array[0] << 0) & 0xFF; They'll start out with junk data, you'll be ORing in valid data with the junk which will result in junk. Commented Oct 28, 2016 at 14:52

2 Answers 2

4

What you have written is not correct. I assume that you intented to build an unsigned char buffer containing in that order:

  • the two lowest byte of the representation of int value 12345
  • a byte containing the representation of char value -1
  • the 4 lowest bytes containing the representation of long value 12174723939

You should have written:

array[0] = (a >> 0) & 0xFF;  // lowest byte
array[1] = (a >> 8) & 0xFF;  // next
array[2] = b;   // cast a char to an unsigned char
array[3] = (c >> 0) & 0xFF;  // lowest byte of c
array[4] = (c >> 8) & 0xFF;
array[5] = (c >> 16) & 0xFF;
array[6] = (c >> 24) & 0xFF;

And you should not send the whole buffer but only the interesting part: 7 bytes:

send(socket, array, 7, 0);

In the receiver part, you rebuild the values from their bytes:

a = array[0];  // start with an initial value
a |= array[1] >> 8;
b = array[2];  // is already a single byte
c = array[3];
c |= array[4] >> 8;
c |= array[5] >> 16;
c |= array[6] >> 24;

Note: as you explictely deal with endianness by sending the lowest byte first, this could be used across machines using different endiannesses

Sign up to request clarification or add additional context in comments.

3 Comments

i tried it out and two things didnt work yet: - casting a char to an unsigned char. when i print out these values they are 255 (for -1) and 254 (for -2). i think thats fine so far. but on the other side i dont receive those values always. sometimes when i send different negative values i get positive values instead. do you know why? - storing the array values in new variables works better with << instead of >>. im working with for-routines and maybe i have some calculation issues as well.
@Frechdachs: 0xFF (or 255) is the representation in 2 complement of (char) -1. Said differently (unsigned char) 255 and (signed char) -1 share the same binary representation : 0xFF.
Bellesta: so there is no chance to see if i receive a -1 or 255? my code below is what i have for now.
1

On the receiver side you should think in reverse order

a += array[1];
a<<=8;
a += (array[0]);

But take note that left shift signed value is UB as standards says

6.5.7.4

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

1 Comment

thank you. so i have to start at the last byte of the whole array and go backwards to the first right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.