I’m working with the NetLink socket library ( https://sourceforge.net/apps/wordpress/netlinksockets/ ), and I want to send some binary data over the network in a format that I specify.
The format I have planned is pretty simple and is as follows:
-
Bytes 0 and 1: an opcode of the type uint16_t (i.e., an unsigned integer always 2 bytes long)
-
Bytes 2 onward: any other data necessary, such as a string, an integer, a combination of each, etc.. the other party will interpret this data according to the opcode. For example, if the opcode is 0 which represents “log in”, this data will consist of one byte integer telling you how long the username is, followed by a string containing the username, followed by a string containing the password. For opcode 1, “send a chat message”, the entire data here could be just a string for the chat message.
Here’s what the library gives me to work with for sending data, though:
void send(const string& data);
void send(const char* data);
void rawSend(const vector<unsigned char>* data);
I’m assuming I want to use rawSend() for this.. but rawSend() takes unsigned chars, not a void* pointer to memory? Isn’t there going to be some loss of data here if I try to cast certain types of data to an array of unsigned chars? Please correct me if I’m wrong.. but if I’m right, does this mean I should be looking at another library that has support for real binary data transfer?
Assuming this library does serve my purposes, how exactly would I cast and concatenate my various data types into one std::vector? What I’ve tried is something like this:
#define OPCODE_LOGINREQUEST 0
std::vector<unsigned char>* loginRequestData = new std::vector<unsigned char>();
uint16_t opcode = OPCODE_LOGINREQUEST;
loginRequestData->push_back(opcode);
// and at this point (not shown), I would push_back() the individual characters of the strings of the username and password.. after one byte worth of integer telling you how many characters long the username is (so you know when the username stops and the password begins)
socket->rawSend(loginRequestData);
Ran into some exceptions, though, on the other end when I tried to interpret the data. Am I approaching the casting all wrong? Am I going to lose data by casting to unsigned chars?
Thanks in advance.
I like how they make you create a vector (which must use the heap and thus execute in unpredictable time) instead of just falling back to the C standard
(const void* buffer, size_t len)tuple, which is compatible with everything and can’t be beat for performance. Oh, well.You could try this:
This uses
insertwhich should optimize better than a hand-written loop withpush_back(). It also won’t leak the buffer ifrawSendtosses an exception.NOTE: Byte order must match for the platforms on both ends of this connection. If it does not, you’ll need to either pick one byte order and stick with it (Internet standards usually do this, and you use the
htonlandhtonsfunctions) or you need to detect byte order (“native” or “backwards” from the receiver’s POV) and fix it if “backwards”.