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

 /*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/ #ifndef __ASYNCACCEPT_H_
#define __ASYNCACCEPT_H_ #include "Log.h"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/address.hpp>
#include <functional>
#include <atomic> using boost::asio::ip::tcp; class AsyncAcceptor
{
public:
typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex); 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))
{
} template<class T>
void AsyncAccept(); template<AcceptCallback acceptCallback>
void AsyncAcceptWithCallback()
{
tcp::socket* socket;
uint32 threadIndex;
std::tie(socket, threadIndex) = _socketFactory();
_acceptor.async_accept(*socket, [this, socket, threadIndex](boost::system::error_code error)
{
if (!error)
{
try
{
socket->non_blocking(true); acceptCallback(std::move(*socket), threadIndex);
}
catch (boost::system::system_error const& err)
{
TC_LOG_INFO("network", "Failed to initialize client's socket %s", err.what());
}
} if (!_closed)
this->AsyncAcceptWithCallback<acceptCallback>();
});
} bool Bind()
{
boost::system::error_code errorCode;
_acceptor.open(_endpoint.protocol(), errorCode);
if (errorCode)
{
TC_LOG_INFO("network", "Failed to open acceptor %s", errorCode.message().c_str());
return false;
} _acceptor.bind(_endpoint, errorCode);
if (errorCode)
{
TC_LOG_INFO("network", "Could not bind to %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str());
return false;
} _acceptor.listen(boost::asio::socket_base::max_connections, errorCode);
if (errorCode)
{
TC_LOG_INFO("network", "Failed to start listening on %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str());
return false;
} return true;
} void Close()
{
if (_closed.exchange(true))
return; boost::system::error_code err;
_acceptor.close(err);
} void SetSocketFactory(std::function<std::pair<tcp::socket*, uint32>()> func) { _socketFactory = func; } private:
std::pair<tcp::socket*, uint32> DefeaultSocketFactory() { return std::make_pair(&_socket, ); } tcp::acceptor _acceptor;
tcp::endpoint _endpoint;
tcp::socket _socket;
std::atomic<bool> _closed;
std::function<std::pair<tcp::socket*, uint32>()> _socketFactory;
}; template<class T>
void AsyncAcceptor::AsyncAccept()
{
_acceptor.async_accept(_socket, [this](boost::system::error_code error)
{
if (!error)
{
try
{
// this-> is required here to fix an segmentation fault in gcc 4.7.2 - reason is lambdas in a templated class
std::make_shared<T>(std::move(this->_socket))->Start();
}
catch (boost::system::system_error const& err)
{
TC_LOG_INFO("network", "Failed to retrieve client's remote address %s", err.what());
}
} // lets slap some more this-> on this so we can fix this bug with gcc 4.7.2 throwing internals in yo face
if (!_closed)
this->AsyncAccept<T>();
});
} #endif /* __ASYNCACCEPT_H_ */

//============================================================================

template<class SocketType>
class NetworkThread

类使用多线程执行socket的管理

那么类的成员变量及作用如后

typedef std::vector<std::shared_ptr<SocketType>> SocketContainer;  //socket容器进行socket指针的存储管理

std::atomic<int32> _connections;    //原子计数 多线程下记录连接数目
std::atomic<bool> _stopped;   //原子bool型flag 标记此线程是否停止

std::thread* _thread;      //线程指针

SocketContainer _sockets;   //socket容器进行socket指针的存储管理

std::mutex _newSocketsLock;  //多线程互斥变量
SocketContainer _newSockets;  //另一个socket容器

//boost 设置常规变量

boost::asio::io_service _io_service;
tcp::socket _acceptSocket;
boost::asio::deadline_timer _updateTimer;

从  void Run()函数入手

void Run()的功能如下

定时异步执行  Update函数 ,运行_io_service

_updateTimer.expires_from_now(boost::posix_time::milliseconds(10));
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
_io_service.run();

void Update()函数

在加锁情况下 将_newSockets容器socket指针添加到_sockets ==》  AddNewSockets();

并移除那些update失败的socket==》_sockets.erase(。。。。。。

再次定时异步调用update

函数作用应该是定时清除无效socket 具体效果还需要在后继代码中看看 template<typename SocketType> 中SocketType的update函数的具体作用

整个类代码如下

 /*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/ #ifndef NetworkThread_h__
#define NetworkThread_h__ #include "Define.h"
#include "Errors.h"
#include "Log.h"
#include "Timer.h"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <atomic>
#include <chrono>
#include <memory>
#include <mutex>
#include <set>
#include <thread> using boost::asio::ip::tcp; template<class SocketType>
class NetworkThread
{
public:
NetworkThread() : _connections(), _stopped(false), _thread(nullptr),
_acceptSocket(_io_service), _updateTimer(_io_service)
{
} virtual ~NetworkThread()
{
Stop();
if (_thread)
{
Wait();
delete _thread;
}
} void Stop()
{
_stopped = true;
_io_service.stop();
} bool Start()
{
if (_thread)
return false; _thread = new std::thread(&NetworkThread::Run, this);
return true;
} void Wait()
{
ASSERT(_thread); _thread->join();
delete _thread;
_thread = nullptr;
} int32 GetConnectionCount() const
{
return _connections;
} virtual void AddSocket(std::shared_ptr<SocketType> sock)
{
std::lock_guard<std::mutex> lock(_newSocketsLock); ++_connections;
_newSockets.push_back(sock);
SocketAdded(sock);
} tcp::socket* GetSocketForAccept() { return &_acceptSocket; } protected:
virtual void SocketAdded(std::shared_ptr<SocketType> /*sock*/) { }
virtual void SocketRemoved(std::shared_ptr<SocketType> /*sock*/) { } void AddNewSockets()
{
std::lock_guard<std::mutex> lock(_newSocketsLock); if (_newSockets.empty())
return; for (std::shared_ptr<SocketType> sock : _newSockets)
{
if (!sock->IsOpen())
{
SocketRemoved(sock);
--_connections;
}
else
_sockets.push_back(sock);
} _newSockets.clear();
} void Run()
{
TC_LOG_DEBUG("misc", "Network Thread Starting"); _updateTimer.expires_from_now(boost::posix_time::milliseconds());
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
_io_service.run(); TC_LOG_DEBUG("misc", "Network Thread exits");
_newSockets.clear();
_sockets.clear();
} void Update()
{
if (_stopped)
return; _updateTimer.expires_from_now(boost::posix_time::milliseconds());
_updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this)); AddNewSockets(); _sockets.erase(std::remove_if(_sockets.begin(), _sockets.end(), [this](std::shared_ptr<SocketType> sock)
{
if (!sock->Update())
{
if (sock->IsOpen())
sock->CloseSocket(); this->SocketRemoved(sock); --this->_connections;
return true;
} return false;
}), _sockets.end());
} private:
typedef std::vector<std::shared_ptr<SocketType>> SocketContainer; std::atomic<int32> _connections;
std::atomic<bool> _stopped; std::thread* _thread; SocketContainer _sockets; std::mutex _newSocketsLock;
SocketContainer _newSockets; boost::asio::io_service _io_service;
tcp::socket _acceptSocket;
boost::asio::deadline_timer _updateTimer;
}; #endif // NetworkThread_h__

trinitycore 魔兽服务器源码分析(一) 网络的更多相关文章

  1. trinitycore 魔兽服务器源码分析(二) 网络

    书接上文 继续分析Socket.h SocketMgr.h template<class T>class Socket : public std::enable_shared_from_t ...

  2. trinitycore 魔兽服务器源码分析(三) 多线程相关

    先看LockedQueue.h template <class T, typename StorageType = std::deque<T> >class LockedQue ...

  3. tiny web服务器源码分析

    tiny web服务器源码分析 正如csapp书中所记,在短短250行代码中,它结合了许多我们已经学习到的思想,如进程控制,unix I/O,套接字接口和HTTP.虽然它缺乏一个实际服务器所具备的功能 ...

  4. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  5. Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新

    SystemUI系列文章 Android8.1 MTK平台 SystemUI源码分析之 Notification流程 Android8.1 MTK平台 SystemUI源码分析之 电池时钟刷新 And ...

  6. [1]传奇3服务器源码分析一 LoginGate

    服务端下载地址: 点击这里 网上基本上都有分析该源码的分析详解,如:请点击该链接,但容易晕,而且也不全!所以才有了本文! 一.首先来看服务端的LoginGate源码 先来张图比较让人容易理解

  7. python之epoll服务器源码分析

    #!/usr/bin/env python # -*- coding: utf8 -*- import socket, select EOL1 = b'/r/n' EOL2 = b'/r/n/r/n' ...

  8. [6]传奇3服务器源码分析一GameGate

    1. 2. 留存 服务端下载地址: 点击这里

  9. [5]传奇3服务器源码分析一GameServer

    1. 2. 留存 服务端下载地址: 点击这里

随机推荐

  1. 依赖、耦合、解耦、控制反转(IOC)、依赖注入(DI)

    随着net的深入学习,出现了很多概念性的东西需要理解,现在统一记录一下. 1.依赖:现阶段在任何一个有请求作用的系统,都会出现A类调用B类的情况,这时候A类就依赖于B类,A类和B类存在依赖关系. 2. ...

  2. Windows Azure Virtual Network (13) 跨数据中心之间的虚拟网络点对点连接VNet Peering

    <Windows Azure Platform 系列文章目录> 今天是大年初二,首先祝大家新年快乐,万事如意. 在笔者之前的文章中:Windows Azure Virtual Networ ...

  3. 阿里轻量应用服务器 Tomcat 注意的地方 Unsupported major.minor version 52.0(unable to load class

    本地编译工程,提交到远程服务其的tomcat上报这个错 Unsupported major.minor version 52.0(unable to load class com.cl.busines ...

  4. python grib气象数据可视化

    基于Python的Grib数据可视化           利用Python语言实现Grib数据可视化主要依靠三个库——pygrib.numpy和matplotlib.pygrib是欧洲中期天气预报中心 ...

  5. 代码: !AJAX

    http://www.cnblogs.com/cwp-bg/p/7668840.html ajax和jsonp使用总结 2017-10-17 var requestUrl="http://l ...

  6. python3 列表去除重复项保留原序

    l1 = ['a',1,'c','b',2,'b','c','d','a'] l2= sorted(set(l1),key=l1.index) print('l2:',l2) print('l1:', ...

  7. java Integer类以及拆箱和装箱

    package com.ilaw.boson.controller; public class Demo { public static void main(String[] args) { Inte ...

  8. CSS样式学习-3、轮廓、伪类/元素、display-flex布局

    一.轮廓 outline绘制于元素周围的一条线,位于边框边缘外围. 属性规定元素轮廓的样式.颜色.宽度. outline-width轮廓宽度,属性:thin细轮廓.medium中等(默认值).thic ...

  9. python_05 可变类型与不可变类型、集合、字符串格式化

    可变数据类型与不可变数据类型: 1.可变:列表,字典 2.不可变:字符串,数字,元组 访问顺序: 1.顺序访问:字符串,列表,元组 2.映射:字典 集合 由不同元素组成的集合,集合中是一组无序排列的可 ...

  10. Java并发辅助类的使用

    目录 1.概述 2.CountdownLatch 2-1.构造方法 2-2.重要方法 2-3.使用示例 3.CyclicBarrier 3-1.构造方法 3-2.使用示例 4.Semaphore 4- ...