Предполагая, что вы хотите выполнить сериализацию самостоятельно и не использовать буферы протокола Google или какую-либо библиотеку для ее обработки, я бы предложил написать пару функций, подобных этой:
// Serializes (msg) into a flat array of bytes, and returns the number of bytes written
// Note that (outBuf) must be big enough to hold any Message you might have, or there will
// be a buffer overrun! Modifying this function to check for that problem and
// error out instead is left as an exercise for the reader.
int SerializeMessage(const struct Message & msg, char * outBuf)
{
char * outPtr = outBuf;
int32_t sendID = htonl(msg.id); // htonl will make sure it gets sent in big-endian form
memcpy(outPtr, &sendID, sizeof(sendID));
outPtr += sizeof(sendID);
int32_t sendLen = htonl(msg.message_length);
memcpy(outPtr, &sendLen, sizeof(sendLen));
outPtr += sizeof(sendLen);
memcpy(outPtr, msg.message_str, msg.message_length); // I'm assuming message_length=strlen(message_str)+1 here
outPtr += msg.message_length;
return (outPtr-outBuf);
}
// Deserializes a flat array of bytes back into a Message object. Returns 0 on success, or -1 on failure.
int DeserializeMessage(const char * inBuf, int numBytes, struct Message & msg)
{
const char * inPtr = inBuf;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvID = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.id = recvID;
if (numBytes < sizeof(int32_t)) return -1; // buffer was too short!
int32_t recvLen = ntohl(*((int32_t *)inPtr));
inPtr += sizeof(int32_t);
numBytes -= sizeof(int32_t);
msg.message_length = recvLen; if (msg.message_length > 1024) return -1; /* Sanity check, just in case something got munged we don't want to allocate a giant array */
msg.message_str = new char[msg.message_length];
memcpy(msg.message_str, inPtr, numBytes);
return 0;
}
С помощью этих функций вы теперь можете конвертировать Сообщение в простой массив символов и обратно по желанию. Поэтому теперь все, что вам нужно сделать, это отправить массив char через TCP-соединение, получить его на дальнем конце и затем десериализовать массив обратно в структуру Message.
Один недостаток в том, что массивы символов будут переменной длины (из-за наличия строки, которая может быть разной длины), поэтому вашему получателю понадобится простой способ узнать, сколько байтов получить до вызова DeserializeMessage. () в массиве.
Простой способ справиться с этим - всегда отправлять 4-байтовое целое число перед отправкой массива char. 4-байтовое целое число всегда должно быть размером предстоящего массива в байтах. (Обязательно сначала преобразуйте целое число в big-endian с помощью htonl (), прежде чем отправлять его, и преобразуйте его обратно в native-endian на приемнике с помощью htonl () перед его использованием).