Итак, вот что я делаю:
У меня есть серверное приложение (аналогично TcpGenericServerApp
). Он принимает сообщения (подписки) и не отвечает сразу. Соединение остается открытым. Когда происходит какое-либо событие, оно отправляет уведомление всем подключенным клиентам.
Затем клиенты должны проанализировать содержимое пакета. Вот мое определение сообщения:
namespace inet;
enum PacketType
{
SUBSCRIBE = 0;
PUBLISH = 1;
};
//
// Message class for event notification service based on TCP.
//
class EventNotificationMsg extends FieldsChunk
{
int type @enum(PacketType);
string awesomeName;
}
Пока все довольно просто. Проблема в том, что размер пакета составляет 1000B. Этот пакет будет разделен TCP на два сегмента. Теперь я должен дефрагментировать эти пакеты, чтобы преобразовать их в EventNotificationMessage
. Как я могу это сделать? Или есть более простой способ извлечь awesomeName
без необходимости дефрагментировать пакеты.
Еще немного контекста:
- Я использую
TcpAppBase
- Когда я просто пытаюсь преобразовать неполный пакет, я получаю следующую ошибку:
Returning an incomplete chunk is not allowed according to the flags: 4
- Я попытался дефрагментировать его, используя этот пример, но он выдал другую ошибку:
Implicit chunk serialization is disabled to prevent unpredictable performance degradation (you may consider changing the Chunk::enableImplicitChunkSerialization flag or passing the PF_ALLOW_SERIALIZATION flag to peek)
. Код, который я использовал ниже.
void EventNotificationSubscriber::socketDataArrived(TcpSocket *socket, Packet *msg, bool urgent)
{
int bytes = msg->getByteLength();
bytesReceivedSinceReset += bytes;
if (bytesReceivedSinceReset % expectedBytesResponse == 0) {
// we received the last bits of a packet
tempPacket->insertAtBack(msg->peekData());
// the packet should be complete now
const Ptr<const EventNotificationMsg> eventNotificationPacket = msg->peekAtFront<EventNotificationMsg>(b(-1), Chunk::PF_ALLOW_INCORRECT);
std::string name = eventNotificationPacket->awesomeName();
}
// there is nothing more to do
delete tempPacket;
tempPacket = nullptr;
bytesReceivedSinceReset = 0;
} else {
if (tempPacket == nullptr){
tempPacket = new Packet("TempPacket");
}
// this is an incomplete packet
tempPacket->insertAtBack(msg->peekData());
}
// do this last as this will delete the packet :O
TcpAppBase::socketDataArrived(socket, msg, urgent);
}
Определения для переменных класса:
Packet* tempPacket;
int bytesReceivedSinceReset;