对于学校项目,我需要通过网络发送和接收一些名为TLV的数据。
事实上,因为TLV可能很小,所以应用程序会发送一个meta-TLV,它将数据包中的几个TLV分组。
我的问题如下:为了正确建模TLV,我需要创建哪些类?
我不知道是否需要提及所有可能的TLV,但我所知道的是以下内容:
- 每个TLV都有一个字段类型,用于标识TLV的语义 - 每个TLV,但一个具有字段长度。然而对于五个TLV,这个尺寸是固定的 - 两个TLV具有完全相同的字段:类型,长度= 0 -Three TLV具有完全相同的字段:type,length = 8和id。只是类型更改(及其名称)
另一个是完全不同的。
我的第一个想法是使用一个包含枚举的母类TLV来存储所有允许的TLV:
//枚举类以避免冲突
enum class TlvType {
Pad1,
PadN,
Bad,
No,
PeersReq,
Peers,
Data,
IHave,
IDontHave,
INeed,
// Unknown,
};
class Tlv {
private:
virtual void to_stream(std::ostream& output) const = 0;
protected:
uint8_t length_;
public:
virtual TlvType type() const = 0;
/*Solution find here : http://stackoverflow.com/questions/2059058/c-abstract-class-operator-overloading-and-interface-enforcement-question*/
friend std::ostream &operator<<(std::ostream& output, const Tlv& tlv) {
tlv.to_stream(output);
return output;
}
//TO DO : do we really need that this method is virtual ?
virtual uint8_t length() const;
Tlv();
virtual ~Tlv() {}
};
class PadN : public Tlv {
private:
void to_stream(std::ostream& output) const;
static constexpr TlvType code() {return TlvType::PadN;}
public:
TlvType type() const;
PadN();
PadN(uint8_t zero_bytes);
void set_length(uint8_t length);
};
问题是这个代码以某种方式代数类型,引入了大量冗余代码。例如,我需要为每个tlv定义方法TlvType type() const
。由于某些Tlv具有固定的大小,我只想要一个可以改变其大小的设置器。
此外,每个Tlv将以准备好发送到网络的格式格式化。对于序列化来说,这看起来很多。但是,我认为序列化对于这个项目来说太过分了。此外,由于这是一个网络项目,每个学生都使用自己的语言。我们唯一知道的是需要通过网络发送的tlv格式。
因为我的代码非常冗余,我认为我的模型化对TLV来说是错误的。而且我怀疑每个TLV使用一个类。实际上,一旦创建TLV,用户可能不会改变他的TLV。他只想发送它。另一方面存在同样的问题:我需要接收TLV。所以我不确定该怎么做。