|
Posted on 2009-02-01 23:09 S.l.e!ep.¢% 阅读(1518) 评论(0) 编辑 收藏 引用 所属分类: test
修改了 INetwordable 接口, 将网络程序中的“网络通信”抽离出来,方便写单元测试 #include <windows.h> #include <iostream> using namespace std;
// 网络通信协议 /**/////////////////////////////////////////////////////////////////////////////// // struct cmd { int nCmd; };
#pragma pack(1) struct tagClientLogin { cmd header; char username[ 20 ]; char userpwd[ 20 ]; } ;
struct tagRepClientLogin { cmd header; bool bLoginSuccess; }; #pragma pack(1)
#define NETWORK_CMD_LOGIN 1 #define NETWORK_CMD_REP_LOGIN 2 /**///////////////////////////////////////////////////////////////////////////////// // 接口定义 /**///////////////////////////////////////////////////////////////////////////////// class ClientObserver { public : ClientObserver() {} ~ ClientObserver() {} virtual void onRepLogin( bool bLoginSuccess) = 0 ; } ;
/**//* class INetWorkable { public : INetWorkable() {} ~INetWorkable() {} // pvoid : 欲发送的缓冲区; nSize : 缓冲区的大小 virtual bool send( const void * pvoid, int nSize) = 0 ; // 由网络层调用,pvoid: 接收到的数据的缓冲区, nSize : 缓冲区的大小; 返回已经处理的数据长度 virtual int onreceive( const void * pvoid, int nSize) = 0 ; }; */
// 将原先的 INetWorkable 接口拆分成两个类 class INetWorkSendable { public : INetWorkSendable() {} ~INetWorkSendable() {} // pvoid : 欲发送的缓冲区; nSize : 缓冲区的大小 virtual bool send( const void * pvoid, int nSize) = 0 ; };
class INetWorkRecvable { public : INetWorkRecvable() {} ~INetWorkRecvable() {} // 由网络层调用,pvoid: 接收到的数据的缓冲区, nSize : 缓冲区的大小; 返回已经处理的数据长度 virtual int onreceive( const void * pvoid, int nSize) = 0 ; };
class ILogable { public : ILogable() {} ~ ILogable() {} virtual void log(const char* plog) = 0; }; /**///////////////////////////////////////////////////////////////////////////////// // 业务逻辑类 // Client 现在只需要继承 INetWorkRecvable 即可 /**///////////////////////////////////////////////////////////////////////////////// class Client : public INetWorkRecvable { public : Client() { m_pClientObserver = NULL; m_plog = NULL; m_pSendable = NULL; }
virtual ~Client() {} void registerObserver(ClientObserver * p) { m_pClientObserver = p; } void removeObserver() { m_pClientObserver = NULL; } void setLoger(ILogable * p) { m_plog = p; } void removeLoger() { m_plog = NULL; } void setSendable(INetWorkSendable* p) { m_pSendable = p; } void removeSendable(INetWorkSendable* p) { m_pSendable = NULL; } bool SendLogin(const char* name, const char* pwd) { tagClientLogin login; memset( & login, 0 , sizeof (login)); login.header.nCmd = NETWORK_CMD_LOGIN; strncpy(login.username, name, sizeof (login.username)); strncpy(login.userpwd, pwd, sizeof (login.userpwd));
// Sendable 改成了 "组合" 的方式后,每次调用 Send 都要判断, 让我很不爽 if( m_pSendable != NULL ) { return m_pSendable->send(&login, sizeof (login)); } else { return false; } } protected : virtual int onreceive( const void * pvoid, int nSize) { if ( nSize < sizeof (cmd) ) return 0 ; cmd * pheader = (cmd * )pvoid; if ( pheader -> nCmd == NETWORK_CMD_REP_LOGIN ) { if ( nSize < sizeof (tagRepClientLogin) ) return 0 ; tagRepClientLogin * ptagRepClientLogin = (tagRepClientLogin * )pvoid; if ( m_pClientObserver != NULL ) m_pClientObserver -> onRepLogin(ptagRepClientLogin -> bLoginSuccess); return sizeof (tagRepClientLogin); } return 0 ; } private : ClientObserver * m_pClientObserver; ILogable * m_plog; INetWorkSendable* m_pSendable; } ; 测试例子 #include "client.h" #include <string.h>
class testClient : public Client, INetWorkSendable { public: testClient() { memset(m_buf, 0, sizeof(m_buf)); } ~testClient() {} int NetWorkReceive(const void* pvoid, int nSize) { return onreceive(pvoid, nSize); }
virtual bool send(const void * pvoid, int nSize) { copyMemory(pvoid, nSize); return true; } bool cmpMemory(const void* pvoid, int nSize) { return ( 0 == memcmp(m_buf, pvoid, nSize) ); } void copyMemory(const void* pvoid, int nSize) { memcpy(m_buf, pvoid, nSize); }
private: char m_buf[1024]; };
int main() { testClient test; test.setSendable((INetWorkSendable*)&test);
test.SendLogin("test_username", "test_pwd"); tagClientLogin clientlogin; memset(&clientlogin, 0, sizeof(clientlogin)); clientlogin.header.nCmd = NETWORK_CMD_LOGIN; strcpy(clientlogin.username, "test_username"); strcpy(clientlogin.userpwd, "test_pwd"); if( !test.cmpMemory(&clientlogin, sizeof(clientlogin)) ) cout << "test failed" << endl; char szBuf[1024] = {0}; // 摸拟服务器发送的包长度不足 if( 0 != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin) - 10) ) cout << "test failed" << endl; // 摸拟服务器发送的包内容非法 if( 0 != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin)) ) cout << "test failed" << endl; tagRepClientLogin repLogin; repLogin.header.nCmd = NETWORK_CMD_REP_LOGIN; memcpy(szBuf, &repLogin, sizeof(repLogin)); // 摸拟服务器发送了正确的包 if( sizeof(tagRepClientLogin) != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin)) ) cout << "test failed" << endl; return 0; }
|