现在我们一步步来看看实现:
先是TTcpAcceptor,该类仅重载了两个方法,如下:
#include "TCPAcceptor.h" namespace igame { int TTcpAcceptor::validate_connection (const ACE_Asynch_Accept::Result& result, const ACE_INET_Addr &remote, const ACE_INET_Addr& local) { if (m_OnClientValidate.valid()) // 这里激发TOnClientValidate事件 return m_OnClientValidate(remote.get_ip_address(), remote.get_port_number()) ? 0 : -1; else return 0; // 默认允许连接 } TTcpHandler* TTcpAcceptor::make_handler(void) { TTcpHandler* handler = 0; ACE_NEW_RETURN (handler, TTcpHandler(), 0); // 设置事件句柄 handler->setOnClientConnect(m_OnClientConnect); handler->setOnClientDisconnect(m_OnClientDisconnect); handler->setOnDataReceive(m_OnDataReceive); handler->setOnDataSendSucceeded(m_OnDataSendSucceeded); handler->setOnDataSendFailed(m_OnDataSendFailed); return handler; } } // namespace igame
复杂的部分在TTcpHandler,该类不仅需要接收数据(拼包),也要处理发送:
#include "TcpHandler.h" namespace igame { TTcpHandler::TTcpHandler() :m_CurDataMB(0) // 初始化 { } TTcpHandler::~TTcpHandler() { if (handle() != ACE_INVALID_HANDLE) { ACE_OS::closesocket(handle()); // 关闭句柄 #ifdef _DEBUG // 打印调试信息 ACE_TCHAR remoteAddrStr[128]; m_ClientAddr.addr_to_string(remoteAddrStr, sizeof(remoteAddrStr) / sizeof(ACE_TCHAR)); ACE_DEBUG((LM_INFO, ACE_TEXT("Disconnect from %s/n"), remoteAddrStr)); #endif // 客户端断开 m_OnClientDisconnect(m_ClientAddr.get_ip_address(), m_ClientAddr.get_port_number()); if (m_CurDataMB) m_CurDataMB->release(); } } int TTcpHandler::send(unsigned int seq, const char* data, unsigned short dataSize) { ACE_Message_Block* dataMB = 0; ACE_NEW_NORETURN(dataMB, ACE_Message_Block(sizeof(unsigned int) + sizeof(unsigned short) + dataSize)); short len = dataSize; dataMB->copy((const char *)&seq, sizeof(unsigned int)); // 这里没有处理seq dataMB->copy((const char *)&len, sizeof(unsigned short)); dataMB->copy((const char *)data, dataSize); int ret = m_Writer.write(*dataMB, dataMB->length()); // 发送 if (ret == -1) m_OnDataSendFailed(m_ClientAddr.get_ip_address(), m_ClientAddr.get_port_number(), seq, data, dataSize); else m_OnDataSendSucceeded(m_ClientAddr.get_ip_address(), m_ClientAddr.get_port_number(), seq, data, dataSize); return ret; } void TTcpHandler::addresses (const ACE_INET_Addr &remote_address, const ACE_INET_Addr &local_address) { m_ClientAddr = remote_address; // 取得客户端地址 } void TTcpHandler::open(ACE_HANDLE h, ACE_Message_Block& mb) { handle(h); // set handle if (m_Reader.open(*this) == -1) // 允许读 { ACE_ERROR((LM_ERROR, ACE_TEXT("failed to open read handle %i/n"), errno)); delete this; return; } if (m_Writer.open(*this) == -1) // 允许写 { ACE_ERROR((LM_ERROR, ACE_TEXT("failed to open write handle %i/n"), errno)); delete this; return; } // 激发客户端连接事件 m_OnClientConnect(m_ClientAddr.get_ip_address(), m_ClientAddr.get_port_number(), this); initCurDataMB(); m_Reader.read(*m_CurDataMB, m_CurDataMB->space()); // 读数据 } void TTcpHandler::handle_read_stream(const ACE_Asynch_Read_Stream::Result& result) { ACE_Message_Block& mb = result.message_block(); if (!result.success() || result.bytes_transferred() == 0) // no data or failed? { mb.release(); delete this; } else { if (this->m_CurDataMB->length() < TCP_PACK_HEADER_SIZE) // try to read header info { this->m_Reader.read(*m_CurDataMB, m_CurDataMB->space()); return ; } TTcpPackHeader* header = reinterpret_cast
然后是TTcpNetThread,该类的实现也相当简单:
#include
最后,对以上三个类进行聚合,封装,就成了TTcp类,在此之前,先定义消息类型:
/** * @name TCP的ACE_Message_Block类型定义 @see ACE_Message_Block * @{ */ /// @brief TCP数据接收 #define TCP_DATA_RECEIVE 0x5505 /// @brief TCP客户端连接 #define TCP_CLIENT_CONNECT 0x5506 /// @brief TCP客户端断线 #define TCP_CLIENT_DISCONNECT 0x5507 /// @brief TCP数据发送 #define TCP_DATA_SEND 0x5508 /// @brief TCP数据发送成功 #define TCP_DATA_SEND_SUCCEEDED 0x5509 /// @brief TCP数据发送失败 #define TCP_DATA_SEND_FAILED 0x550A /** * @} */ /// 默认监听地址:偶的车牌号 #define DEF_LISTENING_PORT 777
现在看看TTcp的实现:
唔,太长了,下一篇吧。
此乃末技,
不知何用。
堆砌字数,
凑成更新。
走过路过,
不要错过。