2011年2月24日 星期四

用ACE練習寫個簡單的server class(上)

曾經想用ACE來寫server,只是學了一下,就放著了...,3年前的事了吧,現在來回味一下....



class CSBNet {
public:
CSBNet(void);
~CSBNet();
bool Start(int port,int scount);
bool Start(int scount);
bool End(void);
void Send(int id, char *data );
char *Receive(void);
private:
SBaseNet *Net;
};

這樣使用起來較簡便,Start後,server就算啟動了,傳送時帶上要傳給client的索引和資料就可以了.
至於接收的Receive則是要把收到資料轉型為CmdPacker的結構


struct CmdPacker//解開的令命包資料
{
int cmd;//從queqe接收的命令
int id;//某個client的索引
int num;//分配的編號
int bsize;//位元組數
char data[1024];
};

雖然是亂七八糟的設計,但使用起來是很輕便的...,其實CSBNet是將SBaseNet再做一次包裝,主要的重點是在SBaseNet類別...


class SBaseNet : public ACE_Task_Base
{
public:
SBaseNet();
~SBaseNet();
bool Start(int scount);
bool Start(int port,int scount);
bool End(void);
void Send(int id, char *data );
char *Receive(void);
virtual int svc();
private:
HA_Proactive_Acceptor aio_acceptor;
int Port;
};
看起來和CSBNet 很像,但前面說過了,CSBNet只是再包一層而已,為什麼要這樣?記得當初是想隔開ACE相關的檔案的,使用CSBNet類時,載入dll就好了,完全不用再管ACE相關配置,因為一些設定還滿煩人的.

接下來的重點是這個

class HA_Proactive_Acceptor : public ACE_Asynch_Acceptor<HA_Proactive_Service>  //異步連接接收器,監聽客戶的請求
{
public:
HA_Proactive_Acceptor();
  HA_Proactive_Acceptor(int scount);
  ~HA_Proactive_Acceptor();
  void free_handler( HA_Proactive_Service * service );
  void Destroy(void);
  void init_handlers(int scount);//在先產生好處理對像,在make_handler內時,就不用new出來了
  RecvQueue RQData;//接收的資料存放處
private:
  //make_handler 為 ACE_Asynch_Acceptor類的虛函式,原本的功能為,有連線連入時,會產生一個服務處理對像
  virtual HA_Proactive_Service *make_handler (void);//客戶連接請求到達時,會自動週用此方法
  virtual int validate_connection(const ACE_Asynch_Accept::Result& result,  const ACE_INET_Addr &remote, const ACE_INET_Addr& local);//可以做ip黑名單
public:
std::map<int, CData> mpInfo;            // 注冊客戶端信息表
typedef std::list<HA_Proactive_Service *> T_Handler_List;
T_Handler_List handler_list_;//事件處理器的指標陣列,一個客戶端分配一個,用完後回收
HA_Proactive_Service *ser;//handler_list_ 指向的實體
int cNum;//連線登入後,分配的號碼
int ServiceCount;
};

這邊開始使用ACE了,再附上其它的class


class RecvQueue : public ACE_Task<ACE_MT_SYNCH>
{
public:
RecvQueue();
virtual ~RecvQueue();
int open(void);
int close(void);
char* Receive(void);
private:
char ReadBuf[65535];
};


class HA_Proactive_Service : public ACE_Service_Handler  //事件處理器,處理所有異步操作的結果
{
public:
HA_Proactive_Service();
virtual ~HA_Proactive_Service ();
void init( HA_Proactive_Acceptor * acceptor, int id );
virtual void open (ACE_HANDLE h, ACE_Message_Block& message_block);//客戶端連接成功後調用
virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
virtual void handle_time_out(const ACE_Time_Value &tv, const void *p);

void SendData(char *buf);

private:
ACE_Asynch_Read_Stream reader_;//異步讀取器
ACE_Asynch_Write_Stream writer_;//異步寫入器
ACE_Message_Block *recv_data_;//接收的資料
int initiate_read_stream(void);
CmdPacker recvpack;
public:
HA_Proactive_Acceptor *acceptor_;
CData   stAppid;//客戶端資料
};

一些自定的結構


ypedef struct s_CData//客戶端資料
{
std::string  sIp;               // 客戶端IP
int    iPort;               // 客戶端連接到服務端的端口
int id;
bool   bOnline;              // 在線狀態
int num;//使用時分配的編號 0:未使用
}CData;

struct PacketHeader//數據包的包頭
{
ACE_HANDLE handler;
char length[4];
};

struct send_data//傳送的字串資料包
{
   char len[4];
    char cmd[4];
   char data[256];
};

以上主要都是在.h內所做的一些宣告,下次再說明.cpp內的程式碼

沒有留言:

張貼留言