-2

I'm trying to send arrays trough the net with winsock2. Now, i read microsoft disabled sending raw pointers, but you can still send un-edited binary data by casting the pointer to char*:

send(rsock, (char*)&counter, len, 0);

However, the problem is putting the data back in an array when it reaches the client. here, pass is the binary data. That's how I do fot integers, bools and doubles.

    recv(sock, pass, sizeof(int), 0);
    refresh =  (int((void*)&pass));
    recv(sock, pass, sizeof(bool[4800][254]), 0);
    **key = (bool)&pass;
    recv(sock, pass, sizeof(double[4800][254]), 0);
    **mil = (double)&pass;

Integers aren't arrays, while bool and doubles are stored in 2 dimensional arrays. Now, the compiler says this code works for int and bool but for doubles it says "'type cast' : cannot convert from 'char **' to 'double'" "invalid type conversion" even though I'm trying to put raw data in it. Have I done something wrong? Is there any other workaround to send arrays? Thanks in advance.

EDIT: also, I still haven't tried the code with another PC, so I highly doubt the conversion for ints and bools is done right.

Alex
  • 45
  • 1
  • 7
  • 1
    Where on earth did you 'read [that] Microsoft disabled sending raw pointers'? You can send anything you like. Whether it *means anything* at the receiver is another question. – user207421 Aug 07 '14 at 01:34
  • I didn't recall on what exact question I read it, but it was on stack overflow - and by the way, *send(rsock, &counter, len, 0);* with a double doesn't compile, I have to use *send(rsock, (char*)&counter, len, 0);*. There is also a multiplication symbol after char, but the website format doesn't show it. – Alex Aug 07 '14 at 01:39
  • 1
    You misread, or misremembered. There's no match for 'Microsoft disabled sending raw pointers' on this entire site other than this question. Your problem is to do with *compilation errors,* not 'Microsoft disabled sending raw pointers'. – user207421 Aug 07 '14 at 01:43
  • Well considering I'm misremembering, have you got any clues for the send problem or for the cast problem? Thanks. – Alex Aug 07 '14 at 01:48
  • There is no 'send problem'. There is a cast problem, which is just C programming, and there is a problem with your `recv()` code: you're assuming that it fills the buffer. It isn't contracted to do that. You need to store the result of `recv()` into a variable and check it for -1, check it for 0, and otherwise use it as the number of bytes received; if that's enough for the next piece of code, OK, otherwise loop. – user207421 Aug 07 '14 at 02:08

2 Answers2

3

Microsoft didn't disable sending anything. The fact is that sending a pointer will simply be of no use to the remote peer. A pointer is simply a memory address, and it is useless to know the address if the information is not there.

The problem you are probably facing is that this array is too big to fit the send buffer, that by default can hold only 64KB.

Pay attention to the return values of send() and recv() to know how much data you actually read/sent in that transaction. It will not always be the same size you told the function to do, as it is often split in pieces smaller than 4KB. You will have to manage the transmission of this information in pieces to fill your entire array.

Craig McQueen
  • 41,871
  • 30
  • 130
  • 181
Havenard
  • 27,022
  • 5
  • 36
  • 62
  • You are right, but the problem i'm talking about in this question is not that the pointer doesn't reach the client, I was looking for a way to pull the pointer back into the array, seen that the one i tried works for bools but not for doubles for some reason unknown to me. – Alex Aug 07 '14 at 01:45
  • @Alex The issue that you're seeing is one where you believe that you can turn pointers into data. That is not the way it works. What you do is send the *data* (not the pointer) over the socket, and then the receiver has to take that data and recreate the data structure(s) on that side. Pretend you're trying to save data to a file, and then in another program, read the file and reconstitute the data. How would you do that? It's the same principle. – PaulMcKenzie Aug 07 '14 at 02:23
0

Have I done something wrong?

Well...

  • by default, send and recv don't guarantee to return only after all the buffer you've supplied is either sent or received; they may return as soon as they've enqueued a bit more data for sending, or after receipt of a bit more data that you might be able to process... the buffer size supplied is just an upper limit to your request, not a minimum. If you want to ensure recv doesn't return until the full buffer has been populated, add the MSG_WAITALL flag as a final parameter. For send you must loop sending further parts of your output buffer.

  • check you return codes... send and recv tell you of errors and have pretty little numbers that give you clues as to the cause and resolution

  • "the compiler says this code works" - no it doesn't... it says your code requests something it's prepared to compile, full of casts that it isn't meant to try to verify, most of which will crash at runtime

Then there's this:

recv(sock, pass, sizeof(int), 0);
refresh =  (int((void*)&pass));
recv(sock, pass, sizeof(bool[4800][254]), 0);
**key = (bool)&pass;
recv(sock, pass, sizeof(double[4800][254]), 0);
**mil = (double)&pass;

I'm not even going to begin to say what's wrong with all that... let's just talk about what might work (might being discussed below):

template <typename T>
void get(int sock, T& t)
{
    if (recv(sock, (char*)&t, sizeof t, MSG_WAITALL) != sizeof t)
        throw std::runtime_error("error while reading data from socket");
}

int refresh;
get(refresh);

bool key[4800][254];
get(key);

double mil[4800][254];
get(mil);

If your sending and receiving systems, compilers, compiler flags, executables etc. differ in any way then this may not work anyway as:

  • up until C++03 compilers weren't required to use any particular type to store bool, so who knows if your sending and receiving side will match

  • big and little endian systems have different byte ordering which can break naive binary transfers like this

  • the size of int may vary

Ultimately, a more robust way to do this would be to use the boost serialisation library.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • I understand your disappointing, but this wasn't supposed to be final code, i would have checcked the return as soon as the casts would have worked. Anyway, thanks, i'll follow your tips. Oh. And are you sure the boost serialization library would work woth socket? – Alex Aug 07 '14 at 10:36
  • @Alex: You're welcome. Re boost serialisation and sockets - there's some answers/links in existing questions - e.g. [here](http://stackoverflow.com/questions/4087263/serialize-and-send-objects-by-tcp-using-boost). Cheers. – Tony Delroy Aug 08 '14 at 02:45