trinitycore是游戏服务器的开源代码 许多玩家使用魔兽的数据来进行测试 ,使用它来假设魔兽私服。
官方网址 https://www.trinitycore.org/
类似的还有mangos 和 kbengine 不过mangos使用庞大的ACE网络框架
kbengine使用自写网络库 两者均使用了多语言进行开发
作为trinitycore 主要使用c++。代码比较好读,就开启本篇这个代码阅读的坑
代码要求具备c++11的function shared_ptr 指针的相关知识
以及了解阅读过boost asio网络库的文档和示例代码的相关知识
先从网络看起
大致看了下 trinitycore使用boost asio作为网络库
大致就是这么几个代码
class AsyncAcceptor 顾名思义 是异步accept
构造函数 简单的初始化类中变量 无他
AsyncAcceptor(boost::asio::io_service& ioService, std::string const& bindIp, uint16 port) :
_acceptor(ioService), _endpoint(boost::asio::ip::address::from_string(bindIp), port),
_socket(ioService), _closed(false), _socketFactory(std::bind(&AsyncAcceptor::DefeaultSocketFactory, this))
{
}
void AsyncAcceptWithCallback() 函数
1 使用_socketFactory产生socket指针复制给类变量
tcp::socket* socket;
std::tie(socket, threadIndex) = _socketFactory();
2 将初始化时传入的函数指针AcceptCallback在ACCEPT时候调用
typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex);
acceptCallback(std::move(*socket), threadIndex);
并再次进入 AsyncAcceptWithCallback函数等待下次accept;
if (!_closed)
this->AsyncAcceptWithCallback<acceptCallback>();
bool Bind()函数将类中accpter与指定的协议绑定bind 并进行监听listen
template<class T>
void AsyncAcceptor::AsyncAccept()函数
不设置回调函数 而是将accept的socket转化为 类型T的指针 并调用T->start();
并且再次进入AsyncAccept()等待下次accept
1 /* 2 * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation; either version 2 of the License, or (at your 7 * option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef __ASYNCACCEPT_H_ 19 #define __ASYNCACCEPT_H_ 20 21 #include "Log.h" 22 #include <boost/asio/ip/tcp.hpp> 23 #include <boost/asio/ip/address.hpp> 24 #include <functional> 25 #include <atomic> 26 27 using boost::asio::ip::tcp; 28 29 class AsyncAcceptor 30 { 31 public: 32 typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex); 33 34 AsyncAcceptor(boost::asio::io_service& ioService, std::string const& bindIp, uint16 port) : 35 _acceptor(ioService), _endpoint(boost::asio::ip::address::from_string(bindIp), port), 36 _socket(ioService), _closed(false), _socketFactory(std::bind(&AsyncAcceptor::DefeaultSocketFactory, this)) 37 { 38 } 39 40 template<class T> 41 void AsyncAccept(); 42 43 template<AcceptCallback acceptCallback> 44 void AsyncAcceptWithCallback() 45 { 46 tcp::socket* socket; 47 uint32 threadIndex; 48 std::tie(socket, threadIndex) = _socketFactory(); 49 _acceptor.async_accept(*socket, [this, socket, threadIndex](boost::system::error_code error) 50 { 51 if (!error) 52 { 53 try 54 { 55 socket->non_blocking(true); 56 57 acceptCallback(std::move(*socket), threadIndex); 58 } 59 catch (boost::system::system_error const& err) 60 { 61 TC_LOG_INFO("network", "Failed to initialize client's socket %s", err.what()); 62 } 63 } 64 65 if (!_closed) 66 this->AsyncAcceptWithCallback<acceptCallback>(); 67 }); 68 } 69 70 bool Bind() 71 { 72 boost::system::error_code errorCode; 73 _acceptor.open(_endpoint.protocol(), errorCode); 74 if (errorCode) 75 { 76 TC_LOG_INFO("network", "Failed to open acceptor %s", errorCode.message().c_str()); 77 return false; 78 } 79 80 _acceptor.bind(_endpoint, errorCode); 81 if (errorCode) 82 { 83 TC_LOG_INFO("network", "Could not bind to %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str()); 84 return false; 85 } 86 87 _acceptor.listen(boost::asio::socket_base::max_connections, errorCode); 88 if (errorCode) 89 { 90 TC_LOG_INFO("network", "Failed to start listening on %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str()); 91 return false; 92 } 93 94 return true; 95 } 96 97 void Close() 98 { 99 if (_closed.exchange(true)) 100 return; 101 102 boost::system::error_code err; 103 _acceptor.close(err); 104 } 105 106 void SetSocketFactory(std::function<std::pair<tcp::socket*, uint32>()> func) { _socketFactory = func; } 107 108 private: 109 std::pair<tcp::socket*, uint32> DefeaultSocketFactory() { return std::make_pair(&_socket, 0); } 110 111 tcp::acceptor _acceptor; 112 tcp::endpoint _endpoint; 113 tcp::socket _socket; 114 std::atomic<bool> _closed; 115 std::function<std::pair<tcp::socket*, uint32>()> _socketFactory; 116 }; 117 118 template<class T> 119 void AsyncAcceptor::AsyncAccept() 120 { 121 _acceptor.async_accept(_socket, [this](boost::system::error_code error) 122 { 123 if (!error) 124 { 125 try 126 { 127 // this-> is required here to fix an segmentation fault in gcc 4.7.2 - reason is lambdas in a templated class 128 std::make_shared<T>(std::move(this->_socket))->Start(); 129 } 130 catch (boost::system::system_error const& err) 131 { 132 TC_LOG_INFO("network", "Failed to retrieve client's remote address %s", err.what()); 133 } 134 } 135 136 // lets slap some more this-> on this so we can fix this bug with gcc 4.7.2 throwing internals in yo face 137 if (!_closed) 138 this->AsyncAccept<T>(); 139 }); 140 } 141 142 #endif /* __ASYNCACCEPT_H_ */