S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

测试网络程序 2

Posted on 2009-02-01 23:09 S.l.e!ep.¢% 阅读(1476) 评论(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, 0sizeof(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, 0sizeof(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};
    
    
// 摸拟服务器发送的包长度不足
    if0 != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin) - 10) )
        cout 
<< "test failed" << endl;
    
    
// 摸拟服务器发送的包内容非法
    if0 != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin)) )
        cout 
<< "test failed" << endl;
    
    tagRepClientLogin repLogin;
    repLogin.header.nCmd 
= NETWORK_CMD_REP_LOGIN;
    memcpy(szBuf, 
&repLogin, sizeof(repLogin));
    
    
// 摸拟服务器发送了正确的包
    ifsizeof(tagRepClientLogin) != test.NetWorkReceive(szBuf, sizeof(tagRepClientLogin)) )
        cout 
<< "test failed" << endl;
    
    
return 0;
}

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理