Chris wrote:
// MY question is when receiving
// ** 2 Different Alternatives Below
// 1
Message msg = conn.reveive()
int type = msg.getType();
switch(type) {
case LOGIN:
// create login message?
}
// 2
std::vector<char> byteBuffer = conn.recieve();
LoginMessage msg = MsgFactory::CreateBuildMessage(byteBuffer);
The problem with (2) is that you are assuming the message is a LoginMessage. (I
guess this is on the server, otherwise the client would do the same for
LoginMessageReply.) I'm not sure why this is guaranteed. For example, (1) does
not attempt to identify the message as a particular type.
From my perspective, (2) is nicer, but should be expressed as
Message *msg = MsgFactory::CreateBuildMessage(buf);
Then, you can use polymorphism to get the correct behavior out of msg; e.g.,
if(msg->error()){
std::cerr << "error: " << msg->tostring() << std::endl;
return 1;
}
yielding
error: username/password not recognized
OTOH, you may need to cast msg to an appropriate type depending on your server
state machine in order to get certain values. For example, if you are in the
"login request" state, you may need
l->username()
l->password()
In this case, I think you can use dynamic_cast<LoginMessage*>() to check whether
the pointer you get back from MsgFactory::CreateBuildMessage() has the right type.
LoginMsg *l = dynamic_cast<LoginMsg*>(MsgFactory::CreateBuildMes sage(buf);
if(l == 0){
// error
}
Another way to do this is to check
msg->type() == MSG_LOGIN_REQ
WLOG regarding your type definitions. This doesn't make much use of the type
system, but the information must already be there in order for the factory to work.
A simpler scheme might be to use specific message poninters to directly access
message data (rather than wrap messages in accessor classes), and simply retain
the Message type for encapsulating generic message operations [error(),
tostring(), packetize(), etc]. This forces you to think carefully about the
structure of the protocol messages since they are all related now by the
placement and encoding of certain fields (e.g., "type" is the first byte,
"error" is the second byte, error strings are ASCII payloads following the error
byte). In any case, this might look like
Message *msg = MsgFactory::CreateBuildMessage(buf);
if(msg->type() == MSG_LOGIN){
LoginMsg *l = msg->payload();
if(login(l->username, l->password) == false){
// error
}
// ...
}
HTH,
/david
--
Andre, a simple peasant, had only one thing on his mind as he crept
along the East wall: 'Andre, creep... Andre, creep... Andre, creep.'
-- unknown