1

The send function in winsock2 accepts only char pointers. How do I send integers or objects through it too?

Pilpel
  • 231
  • 1
  • 7
  • 11

3 Answers3

5

const char *buf which you need to pass to send() function as an argument is just a pointer to array of bytes. You need to convert integers to bytes:

const int MAX_BUF_SIZE = 1024;
int int_data = 4;
const char *str_data = "test";

char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;

memcpy(&int_data, p, sizeof(int_data));
p += sizeof(int_data);

strcpy(p, str_data);
p += strlen(str_data) + 1;

send(sock, buf, p - buf, 0);

free(buf);

and reading code:

const int MAX_BUF_SIZE = 1024;
int int_data = 0;
const char *str_data = NULL;

char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;

recv(sock, buf, MAX_BUF_SIZE, 0);

memcpy(p, &int_data, sizeof(int_data));
p += sizeof(int_data);

str_data = malloc(strlen(p) + 1);
strcpy(str_data, p);
p += strlen(p) + 1;

free(buf);

and complex objects needs to be serialized to stream of bytes.

Note 1: The code sample is valid iff both server and client use the same platforms (x32 / x64 / ...) that means int has the same amount of bytes and byte order is the same.

Note 2: Writing code should check that there is no buffer (MAX_BUF_SIZE) overflow on each step.

Community
  • 1
  • 1
dma_k
  • 10,431
  • 16
  • 76
  • 128
  • for an integer should I use reinterpret_cast(i)? – Pilpel Aug 22 '11 at 09:40
  • 1
    "(that is easy)" - for those who know how to. If you have to ask this question, you're not going to find `htons` and `htonl()`. (@Pilpel: "hton" stands for "Host TO Network"; it changes the order of bytes to match that of TCP/IP. On receive, you'd use a "ntoh" function. Both exist in 's' (short, 16 bits) and 'l' (long, 32 bits) version. – MSalters Aug 22 '11 at 09:45
  • How does this answer my question? the ntoh functions don't take char pointers and make them integers – Pilpel Aug 22 '11 at 11:38
  • @Pilpel: Not directly. It's the step you need to do before `reinterpret_cast(&result_of_htonl)` – MSalters Aug 22 '11 at 11:45
  • I see. So the "host" word in hton could be both client and server code, right? – Pilpel Aug 22 '11 at 11:50
  • @Pilpel: I don't understand, why we need to swap the bytes before putting them to the buffer and then do a reverse operation. I would use `memcpy` to copy bytes (with assumption that `int` = 4 bytes on server and client platform and both platforms are e.g. x86). – dma_k Aug 22 '11 at 13:36
  • I'm confused. Could you post some lines of code to clear things up? – Pilpel Aug 22 '11 at 13:41
  • @Pilpel: I've added the sample. Sorry, it is not tested, but I hope you can catch the idea. – dma_k Aug 22 '11 at 14:33
2

Just store the value into a variable and then type-cast the variable to char*. The send() and recv() functions operate on binary data, despite taking char* parameters.

Sending:

int int_data = 4;
send(sock, (char*) &int_data, sizeof(int), 0);

Reading:

int int_data;
recv(sock, (char*) &int_data, sizeof(int), 0);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Generally, the easiest way is to print the integer or object to a string, and send that string. Textual representations are more portable, and also easier to debug.

std::stringstream may be a useful class both to create the string and parse it on the other end.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • This serialization is ineffective. As long as you don't need a crossplatform portability you can use a memcpy semantik. Take the address of the object and its size and pass address and size to the winsock functions. You will need a cast here. When your data contain pointers to other objects you can't use the memcpy style. In that case you need serialization. – harper Aug 22 '11 at 11:10
  • Ineffective? You even admit it's cross-platform, so it must certainly work. – MSalters Aug 22 '11 at 11:47
  • So assuming I have an object with two data members, x and y, when x = 10 and y = 20. Do you recommend me to send it as plain text like this: "10|20"? – Pilpel Aug 23 '11 at 16:13