|
Posted on 2009-02-01 23:09 S.l.e!ep.¢% 閱讀(1547) 評論(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;
}
|