我想要一个很好的设计来实现主从协议。该协议是专有的,类似于cctalk。我们有:
硕士:HEADER [ DATA ] CHECKSUM
从:HEADER [ DATA ] CHECKSUM
我的选择是为请求和响应设置具体的基类:
class PacketReq {
public:
typedef std::vector<uint8_t> container;
typedef container::const_iterator const_iterator;
PacketCommand command() const
{
return static_cast< PacketCommand >( mBuffer[ 2 ] );
};
const container& data() const
{
return mBuffer;
}
const_iterator begin() const
{
return mBuffer.begin();
}
const_iterator end() const
{
return mBuffer.end();
}
protected:
container mBuffer;
};
class PacketOut1 : public PacketReq {
public:
PacketOut1()
{
mBuffer.reserve( PacketHeaderHelper::HEADER_SIZE );
mBuffer.push_back( /* something. */ );
mBuffer.push_back( /* something. */ );
mBuffer.push_back( /* something. */ );
mBuffer.push_back( /* something. */ );
}
};响应可以是好的响应,也可以是NACK (错误)。我的恳求是:
class PacketRes {
public:
PacketRes(const std::vector<uint8_t>& buffer)
{
if (!checkChecksum( buffer ))
{
throw Error("invalid checksum");
}
PacketHeaderHelper header( buffer );
mCommand = header.command();
if (header.len() > PacketHeaderHelper::HEADER_SIZE)
{
const size_t bodySize = header.len() - PacketHeaderHelper::HEADER_SIZE;
mData.reserve( bodySize );
mData.insert(
mData.end(),
buffer.begin() + PacketHeaderHelper::HEADER_SIZE - 1,
buffer.end() - 1
);
}
}
virtual ~PacketReq() {}
PacketCommand command() const
{
return mCommand;
}
const std::vector<uint8_t>& body() const
{
return mData;
}
private:
bool checkChecksum(const std::vector<uint8_t>& buffer) const
{
/* calc checksum. */
}
private:
std::vector<uint8_t> mData;
PacketCommand mCommand;
};
class PacketInAck : public PacketReq {
public:
PacketInAck(const std::vector<uint8_t>& buffer) : PacketReq( buffer )
{
}
};因此,如果我想提出请求,那么顺序是:
lock_guard
send( const PacketOut& p )
std::unique_ptr< PacketRes > read();但我不喜欢这个设计,但效果很好。
还有其他方法来实现这一点吗?
发布于 2013-06-14 14:22:39
一个可能的预测执行可以是以下几个方面:
所有的包都没有继承,没有接收的包,也没有发送的包。
PacketOutA、PacketOutB、PacketOutC都是具有公共接口的类,它们只有两种方法:begin()和end()来访问内部数据;
接收类有PacketInA、PacketInB等。
类Communication用于允许我向通信端口发送和接收数据。
ReaderAndValidator类允许我获取并验证接收数据包的主体。
Dispatcher类允许我从接收到的邮件中获取一个包(对不起,我的英语.看这个例子..。)
相反,需要使用Device类在域上下文中快速显示我们连接的设备。
/** abstract the communication mechanism. */
class Communication {
public:
Communication ();
template < typename Iterator >
void send( Iterator first, Iterator last ) const
{
// send from first to last to
}
template< typename Iterator >
std::vector< char > read( Iterator first, Iterator last ) const
{
// read from first to last to
}
private:
// internal stuff
};
/** Validate an input packet and get the body */
class ReaderAndValidator {
public:
ReaderAndValidator ( const Communication& comm )
: mComm( comm )
{
}
std::vector< char > read()
{
// read data
return mComm.read( /* params */ );
}
private:
const Communication& mComm;
}
/** Given the PacketOut obtain the corrisponding PacketIn. */
template < typename PacketOut >
class Dispatcher {
Dispatcher()
{
static_assert( false, "unable to instantiate Controller" );
}
};
template <>
class Dispatcher< PacketOutA > {
public:
Dispatcher( const Communication& comm )
: mComm( comm )
{
}
PacketInA send( const PacketOutA & packet ) const
{
mComm.send( std::begin( packet ), std::end( packet ) );
ReaderAndValidator reader( mComm );
auto body = reader.read();
// RVO
PacketInA result( std::begin( body ), std::end( body ) );
return result;
}
private:
const Communication& mComm;
};
// same thing for Controller< PacketOutB >, Controller< PacketOutC > and so on
class Device : private boost::noncopyable {
public:
Device ()
{
// init communication
}
void doPacketOutA( int param )
{
PacketOutA packet( param );
recieve( packet );
}
PacketInB doPacketB()
{
PacketOutB packet();
return recieve( packet );
}
private:
template < typename PacketOutKind >
auto recieve( const PacketOutKind& p ) -> decltype( std::declval< Dispatcher< PacketOutKind > >().send( p ) ) )
{
Dispatcher< PacketOutKind > disp( mCommunication );
return controller.send( p );
}
private:
Communication mCommunication;
};https://codereview.stackexchange.com/questions/27297
复制相似问题