views:

111

answers:

5

I'm using synchronised sockets with a win32 window, and using the send() and recv() function to send data over internet TCP;

what i'm wondering, how would i send some integers or even my own class/structure over the tcp socket? because the send() function only lets me send characters.

Would i just have to send characters and then maybe convert them to integer with atoi()? or if i wanted to send a class structure, would i send many strings over and then put them in the variables.. one by one.

+1  A: 

It isn't sending characters in the textual sense - it's sending contiguous arrays of bytes, which it refers to using a char*. You can point to the bytes of any value type this way, so if you wanted to send an int,

int A = 5;
const char* pBytesOfA = (const char*)&A;
int lengthOfBytes = sizeof(A);

send(socket, pBytesOfA, lengthOfBytes, flags);
Nicholas M T Elliott
+1  A: 

It depends on what you want to do. One simple possibility is:

Let's assume that an int has 32 significant bits and that negative values are encoded in two's-complement. Then you can send one int as four chars:

bool send_int(int fd, int i)
{
  unsigned char buf[4];
  buf[0] = (i >> 24) & 0xff;
  buf[1] = (i >> 16) & 0xff;
  buf[2] = (i >>  8) & 0xff;
  buf[3] = (i >>  0) & 0xff;
  return ((unsigned) send(fd, buf, sizeof buf, 0) == sizeof buf);
}

On the receiving side you have to read four bytes and then combine their values so that they form an int again.

There are many other possibilities for encoding ints and other data types as a stream of bytes. The above is just a simple example.

Roland Illig
Don't do this. I mean don't compare to buffer size. Always keep track of how many bytes you sent. `write(2)` and `send(2)` can legally return less then you are asking to send.
Nikolai N Fetissov
Thanks for the note. The proper fix would be to write a function `sendbytes` that repeatedly tries to send the given buffer (or the remainder of it) until all bytes have been sent or a non-recoverable error occured.
Roland Illig
A: 

You can certainly send a binary buffer via send(). Just cast it to (const char *) in the send call..

tholomew
That will quickly become error-prone if you have different hardware on the sending and the receiving side. Think about byte order, size of `int`, etc.
Roland Illig
I'm assuming the binary buffer has been composed correctly. Perhaps I should have been more explicit.
tholomew
+1  A: 

Rather not do this yourself, use libraries which do this for you, like Boost.Asio and Boost.Serialization.

Boost Asio is a library which replaces sockets and even provides an interface like C++ iostreams and will handle sending/recieving builtin types like int for you.

Boost Serialization enables you to easily serialize your classes so you can send them over the network.

IF you cant use additional libraries, you will have to send the data manually over plain sockets - make sure you dont forget to use htons, ntohs, htonl and ntohl functions, or your code will break when the two communicating computers use different endianess (byte order).

small snippet:

// sender:
unsigned long to_send = 123;
unsigned long to_send_n = htonl(to_send); // convert to network byte order
send(send_socket, (const char*)(&to_send_n), sizeof(unsigned long), flags);

// reciever:
char recv_buf[sizeof(unsigned long)];
recv(recv_socket, recv_buf, sizeof(unsigned long)); //recieve number
unsigned long recieved = ntohl(*((unsigned long*)recv_buf), flags); // convert back to host byte order

Since these functions only exist for unsigned types, you will be limited to unsigned types..

smerlin
A: 

A C(++) char is not the same as a character. A char is simply an integer type with at least (and usually exactly) 8 bits. A char often does represent an ASCII character (or nowadays, a UTF-8 code unit), but it can also represent arbitrary binary data, which is the case with send() and recv().

Now, there are some protocols (e.g., SMTP) which do assume that the data is text, and may mangle binary data that happens to contain bytes like 0x0A (line feed) or 0x00 (C string terminator). In this case, you do need to use a binary-to-text encoding like Base64. But it shouldn't be an issue if you're working with TCP directly.

dan04