Проблема с сериализатором сообщений в симуляции veins_inet

Я пытаюсь настроить проект veins_inet (я реализовал пользовательскую карту SUMO и около 10 узлов. Эта симуляция работает без дополнений, которые я здесь представляю), и, в частности, отправляю сообщение, содержащее скорость, каждому транспортному средству в заданные периоды времени ( это совершенно не соответствует сообщениям, отправляемым во время аварии). Файл .msg, который у меня есть, задается просто:

import inet.common.INETDefs;
import inet.common.packet.chunk.Chunk;

//
// General message definition
//
class GeneralMessage extends inet::FieldsChunk
{
    double Speed;
    
}

и файлы сериализатора, которые я написал для этих сообщений, даны:

// GeneralMessageSerializer.h
#ifndef __GENERALMESSAGESERIALIZER_H
#define __GENERALMESSAGESERIALIZER_H

#include "inet/common/packet/ChunkQueue.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/packet/serializer/FieldsChunkSerializer.h"
#include "inet/common/packet/serializer/SequenceChunkSerializer.h"
#include "GeneralMessage_m.h"

namespace inet {

class GeneralMessageSerializer : public FieldsChunkSerializer
{
  public:
    virtual void serialize(MemoryOutputStream& stream, const Ptr<const Chunk>& chunk) const override;
    virtual const Ptr<Chunk> deserialize(MemoryInputStream& stream) const override;
};


}

#endif // __GENERALMESSAGESERIALIZER_H

// GeneralMessageSerializer.cc
#include "GeneralMessageSerializer.h"
#include "GeneralMessage_m.h"
#include "inet/common/packet/chunk/ByteCountChunk.h"
#include "inet/common/packet/chunk/BytesChunk.h"
#include "inet/common/packet/ChunkBuffer.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/packet/ReassemblyBuffer.h"
#include "inet/common/packet/ReorderBuffer.h"
#include "inet/common/packet/serializer/ChunkSerializerRegistry.h"
#include "inet/common/TimeTag_m.h"

namespace inet {

Register_Serializer(GeneralMessage, GeneralMessageSerializer);

#define ASSERT_ERROR(code, message) try { code; ASSERT(false); } catch (std::exception& e) { ASSERT((int)std::string(e.what()).find(message) != -1); };

void GeneralMessageSerializer::serialize(MemoryOutputStream& stream, const Ptr<const Chunk>& chunk) const
{
    const auto& generalMessage = staticPtrCast<const GeneralMessage>(chunk);
//    auto Speed = stream.getSpeed();
    stream.writeUint32Be(generalMessage->getSpeed());
    stream.writeByteRepeatedly(0, B(generalMessage->getChunkLength()).get());
}

const Ptr<Chunk> GeneralMessageSerializer::deserialize(MemoryInputStream& stream) const
{
    auto generalMessage = makeShared<GeneralMessage>();
    generalMessage->setSpeed(stream.readUint32Be());
    stream.readByteRepeatedly(0, B(generalMessage->getChunkLength()).get());
    return generalMessage;

}}

Это сообщение реализовано в образце приложения veins_inet путем добавления блока кода

int i;
    for(i=25;i<150;i++){
        // every node to send out a general message every second
        auto callback = [this]() {
            auto payload = makeShared<GeneralMessage>();
            auto packet = createPacket("general");
            payload->setChunkLength(B(150));
            payload->setSpeed(traciVehicle->getSpeed());
            timestampPayload(payload);
            packet->insertAtBack(payload);
            sendPacket(std::move(packet));
        };
        timerManager.create(veins::TimerSpecification(callback).oneshotAt(SimTime(i, SIMTIME_S)));
    };

в функции StartApplication файла VeinsInetSampleApplication.cc. Как видите, я бы хотел, чтобы это GeneralMessage передавалось каждую секунду каждым узлом в моделировании, начиная с 25-й секунды. Для справки: у меня есть регистраторы Pcap на каждом узле для записи этих сообщений, но до сих пор мне не удалось сделать сообщение видимым в этих записях, поскольку я подозревал, что оно не сериализуется должным образом.

Ошибка, которую я получаю при попытке запустить это:

Неявная сериализация чанков отключена, чтобы предотвратить непредсказуемое снижение производительности (вы можете изменить флаг Chunk::enableImplicitChunkSerialization или передать флаг PF_ALLOW_SERIALIZATION для просмотра) -- в модуле (VeinsInetSampleApplication) Scenario.node[0].app[0] (id= 110), при t=25с, событие №143

В случае, если это также полезно, вот вывод из последней горстки событий перед появлением ошибки в консоли:

** Событие №133 t=25 Scenario.node[8].ipv4.ip (Ipv4, id=658) в общем (inet::Packet, id=1536)

ИНФОРМАЦИЯ: Получено (inet::Packet) общее из сети. ДЕТАЛИ: Получено дейтаграмма `' с dest=224.0.0.1 INFO:Доставка (inet::Packet)general (178 Б) [[inet::Ipv4Header, длина = 20 Б | inet::UdpHeader, порт: 9001-> 9001, длина полезной нагрузки: 150 Б, длина = 8 Б | Общее сообщение, длина = 150 В]] локально. ПРЕДУПРЕЖДЕНИЕ: Получена дейтаграмма «общая» без адрес источника заполнен INFO:Переход на протокол udp(57) ** Событие №134 t=25 Scenario.node[8].wlan[0].mac (Ieee80211Mac, id=622) в общем (inet::Packet, id=1528)

INFO:Кадр (inet::Packet)общий (208 Б) [[inet::ieee80211::Ieee80211DataHeader, длина = 24 Б | inet::Ieee80211EtherTypeHeader, длина = 2 B | инет:: Ipv4Header, длина = 20 В | inet::UdpHeader, порт:9001->9001, payloadLength:150 Б, длина = 8 В | GeneralMessage, длина = 150 Б | inet::ieee80211::Ieee80211MacTrailer, length = 4 B]] получено от верхний уровень, получатель = 01-00-5E-00-00-01 INFO (Dcf)Scenario.node[8].wlan[0].mac.dcf:Обработка верхнего фрейма: общее ИНФОРМАЦИЯ (PendingQueue)Scenario.node[8].wlan[0].mac.dcf.channelAccess.pendingQueue:Pushing пакет вообще в очередь. ДЕТАЛИ (Dcf)Scenario.node[8].wlan[0].mac.dcf:Запрос канала DETAIL (Конфликт)Scenario.node[8].wlan[0].mac.dcf.channelAccess.contention:Starting конкуренция: cw = 15, slots = 15, slotTime = 0,000013, ifs = 0,000058, eifs = 0,000178 ИНФОРМАЦИЯ (Конфликт)Scenario.node[8].wlan[0].mac.dcf.channelAccess.contention:Scheduling Конец состязания: отложенные слоты = 15, slotTime = 0,000013, lastBusyTime = 20.000152936058, lastIdle = -4611676.018427387903, waitInterval = 0. ** Событие №135 t=25 Scenario.node[0].udp (Udp, id=107) в общем (inet::Packet, id=1529)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=0 ** Событие #136 t=25 Scenario.node[1].udp (Udp, id=170) в общем (inet::Packet, id=1530)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=1 ** Событие №137 t=25 Scenario.node[2].udp (Udp, id=233) в общем (inet::Packet, id=1531)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=2 ** Событие #138 t=25 Scenario.node[3].udp (Udp, id=296) в общем (inet::Packet, id=1532)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=3 ** Событие #139 t=25 Scenario.node[4].udp (Udp, id=359) в общем (inet::Packet, id=1533)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=4 ** Событие №140 t=25 Scenario.node[5].udp (Udp, id=422) в общем (inet::Packet, id=1534)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=5 ** Событие №141 t=25 Scenario.node[7].udp (Udp, id=548) в общем (inet::Packet, id=1535)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=7 ** Событие №142 t=25 Scenario.node[8].udp (Udp, id=611) в общем (inet::Packet, id=1536)

INFO:Общий пакет получен из сети, порт назначения 9001 INFO:Отправка полезная нагрузка до сокета sockId=8 ** Событие №143 t=25 Scenario.node[0].app[0] (VeinsInetSampleApplication, id=110) в общем (inet::Packet, идентификатор = 1529)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы изменили тип сообщения, которое вы отправляете в VeinsInetSampleApplication, но вы не изменили тип ожидаемого полученного сообщения. Итак, в VeinsInetSampleApplication.cc есть что-то вроде этого:

void VeinsInetSampleApplication::processPacket(std::shared_ptr<inet::Packet> pk)
{
  auto payload = pk->peekAtFront<VeinsInetSampleMessage>();  // <-- causes an error
  EV_INFO << "Received packet: " << payload << endl;
  ...

Поэтому при получении пакет обрабатывается как VeinsInetSampleMessage, а не GeneralMessage - это приводит к исключению. Я предлагаю изменить эту строку на:

auto payload = pk->peekAtFront<GeneralMessage>();

И, конечно же, оставшаяся часть processPacket() должна быть изменена соответствующим образом (например, GeneralMessage не содержит roadId, поэтому его нельзя читать).

Спасибо, это сработало отлично! Еще один случайный вопрос, поскольку вы кажетесь большим источником знаний в этой области - знаете ли вы, как (надеюсь, легко) изменить протокол передачи сообщений? По умолчанию в примере приложения это UDP, однако я думаю, что это слишком просто, так как фактическое сообщение в GeneralMessage не записано в файле Pcap, который я позже проанализирую. То есть я хотел бы, чтобы скорость автомобиля была видна в этой записи Pcap. Я вижу из демонстрации Pcap, что, возможно, мне может понадобиться использовать ARP. Это возможно?

user20301597 28.12.2022 13:56
VeinsInetApplicationBase использует многоадресный IPv4-адрес (например, 224.0.0.1) в качестве адреса назначения, поэтому тип транспорта должен быть UDP. Поэтому вы не можете использовать TCP вместо UDP.
Jerzy D. 30.12.2022 09:30

Еще раз спасибо. Можно ли каким-то образом изменить это, чтобы манипулировать типом протокола? Я вижу несколько типов протоколов в примере Pcap Showcase с Inet, но код кажется довольно минимальным, и из него сложно извлечь информацию.

user20301597 31.12.2022 11:55

Другие вопросы по теме