Передать структуру с вектором внутри через сокетC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Передать структуру с вектором внутри через сокет

Сообщение Anonymous »

Мне было сложно сериализовать эту «простую» структуру:

Код: Выделить всё

#define PACKED_STRUCT struct __attribute__((packed))
typedef std::vector bytearray;

static PacketType ReadMemPacketType = 2 + PT_C2S_OFFSET(2);
PACKED_STRUCT ReadMemPayload {
bytearray data;
};
Я пытался превратить вектор в байтовый код uint8_t*, но когда я передаю его через сокет, я получаю указатель массива, а не данные массива. Это также приводит к сбою моего клиента с SIGSEGV, когда он пытается проанализировать отправленный массив указателей.
Это код векторной оболочки:

Код: Выделить всё

template
PACKED_STRUCT NetworkVector {
size_t data_array_size;
T* data_array;

explicit NetworkVector(std::vector vec) : data_array_size(vec.size()), data_array(vec.data()) { }

~NetworkVector() { delete[] data_array; }

NetworkVector() : NetworkVector(std::vector()) { }
NetworkVector(size_t size) : NetworkVector(std::vector(size)) { }
NetworkVector(T* begin, T* end) : NetworkVector(std::vector(begin, end)) { }
NetworkVector(std::vector orig, std::vector extra) : NetworkVector([&]() {
std::vector copy = orig;
copy.insert(copy.end(), extra.begin(), extra.end());
return copy;
}()) { }

static inline std::vector toVector(NetworkVector serializedVec) {
return std::vector(serializedVec.data_array, serializedVec.data_array + serializedVec.data_array_size);
}

};
теперь моя структура выглядит так:

Код: Выделить всё

typedef NetworkVector net_bytearray;
static PacketType ReadMemPacketType = 2 + PT_C2S_OFFSET(2);
PACKED_STRUCT ReadMemPayload {
net_bytearray data;
};
А вот как я сериализую всю свою структуру:

Код: Выделить всё

template
static Packet wrap(PacketType type, T structData) {
byte* dataPtr = reinterpret_cast(&structData);
bytearray data(dataPtr, dataPtr + sizeof(T));
return Packet(type, data); // the constructor automatically createss the header.
}
// wrap the struct first then serialize
bytearray serialize() const {
bytearray serializedHeader(sizeof(PacketHeader));
std::memcpy(serializedHeader.data(), &header, serializedHeader.size());
serializedHeader.insert(serializedHeader.end(), data.begin(), data.end());
return serializedHeader;
}
и вот как я отправляю вектор:

Код: Выделить всё

int Socket::sendData(bytearray data) {
int res = send(socketFd, data.data(), data.size(), 0);
if (res == -1) {
Logger::getLogger()->warn("Failed to send " + std::to_string(data.size()) + " bytes to SocketFd " + std::to_string(socketFd));
}

return res;
}
со всем показанным кодом, вот как я обертываю, сериализую и отправляю данные через сокет.

Код: Выделить всё

packet.sender.socket->sendData(
Packet::wrap(
S2C::ReadMemPacketType,
{ .data = net_bytearray(bytearray({255, 69})) }
).serialize()
);
Сервер отправляет эти байты:

Код: Выделить всё

0x02
0x00
0x00
0x00
0x88
0x20
0x45
0xeb
и клиент получает:

Код: Выделить всё

\x02\x00\x00\x00\x88\x70\x13\xf1
а затем, когда NetworkVector::toVector() был вызван в клиенте:

Код: Выделить всё

Info: Base address is non-null! Convert to std::vector and get the value!
fish: Job 1, './build_android/remdeb_app' terminated by signal SIGSEGV (Address boundary error)
Код является общедоступным и находится здесь:
https://github.com/ThatMG393/remdeb
< /blockquote>

Подробнее здесь: https://stackoverflow.com/questions/793 ... h-a-socket
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»