码迷,mamicode.com
首页 > 其他好文 > 详细

【网络组件】服务器TcpServer

时间:2015-04-04 18:31:13      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

        本节研究服务器TcpServer的实现;


整体类图

技术分享

服务器TcpServer

(1)TcpServer由用户直接使用,生命周期由用户控制,用户设置好相应的回调MessageCallback、ConnectionCallback传递给TcpServer即可;MessageCallback为连接上有接收数据时调用的回调(处理业务逻辑),这些数据存放在连接的应用层接收缓冲区中;ConnectionCallback在连接建立和断开时,都会直接的回调,主要是通知用户进行相应的处理;

(2)在TcpServer中,建立连接描述符和TcpConnection之间的关系,通过stl中map来实现,map<int, TcpConnectionPtr>这样可以高效的查找,删除,插入操作;

(3)TcpServer本身有一个EventLoop,主要用于对接受连接事件的监听,;EventLoopPool也为TcpServer的成员,使用轮转法为每一个新的TcpConnection选择EventLoop;

示意图如下:

技术分享




TcpServer接受连接示意图如下

技术分享


接收数据回调示意图如下

技术分享


TcpServer断开连接示意图如下

技术分享

TcpServer

TcpServer声明

class TcpConnection;
class EventLoop;
class Acceptor;
class EventLoopPool;

class TcpServer final
{
public:
  TcpServer(const TcpServer&) = delete;
  TcpServer& operator=(const TcpServer&) = delete;

  explicit TcpServer(EventLoop* loop, const InetAddress& serverAddr, size_t loopNums);

  void start();

  typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;

  void setMessageCallback(const MessageCallback& cb)
  {
    _messageCallback = cb;
  }

  void setConnectionCallback(const ConnectionCallback& cb)
  {
    _connectionCallback = cb;
  }

private:
  void _newConnection(int connfd, const InetAddress& peerAddr);

  void _removeConnection(const TcpConnectionPtr& conn);
  void _removeConnectionInLoop(const TcpConnectionPtr& conn);

  InetAddress _serverAddr;
  size_t _loopNums;

  EventLoop* _loop;
  std::unique_ptr<Acceptor> _acceptor;
  std::unique_ptr<EventLoopPool> _loopPool;

  std::map<int, TcpConnectionPtr> _connectionMaps;

  MessageCallback _messageCallback;
  ConnectionCallback _connectionCallback;
};
说明几点:

(1)MessageCallback为连接上有接收数据时调用的回调(处理业务逻辑),这些数据存放在连接的应用层接收缓冲区中;ConnectionCallback在连接建立和断开时,都会直接的回调,主要是通知用户进行相应的处理;

(2)在TcpServer中,建立连接描述符和TcpConnection之间的关系,通过stl中map来实现,map<int, TcpConnectionPtr>这样可以高效的查找,删除,插入操作;

(3)TcpServer本身有一个EventLoop,由用户来传入,主要用于对接受连接的事件的监听;EventLoopPool也为TcpServer的成员,使用轮转法为每一个新的TcpConnection选择EventLoop;_loopNums为EventLoopPool的EventLoop数量;

(4)std::unique_ptr<Acceptor> _acceptor是TcpServer的成员,用于接受新连接,_newConnection为注册给_acceptor的回调,当有新连接时,会回调该函数;

(5)_serverAddr为服务器的监听地址;


构造函数

TcpServer::TcpServer(EventLoop* loop, const InetAddress& serverAddr, size_t loopNums) :
    _serverAddr(serverAddr),
    _loopNums(loopNums),
    _loop(loop),
    _acceptor(new Acceptor(_serverAddr, _loop)),
    _loopPool(_loopNums > 0 ? (new EventLoopPool(_loopNums)) : nullptr)
{
  _acceptor->setNewConnectionCallback(std::bind(&TcpServer::_newConnection, this, std::placeholders::_1, std::placeholders::_2));
}

说明几点:

(1)当_loopNums不大于0时,就使用master线程中EventLoop进行对TcpConnection的管理,意味着这是一个单线程单EventLoop的服务器;

启动EventLoopPool中各个IO线程

void TcpServer::start()
{
  _loopPool->start();
}


接受新连接

void TcpServer::_newConnection(int connfd, const InetAddress& peerAddr)
{
  EventLoop* loop;
  if ( _loopPool)
    {
      loop =  _loopPool->getNextLoop();
    }
  else
    {
      loop = _loop;
    }

  LOG_INFO << "TcpServer::_newConnection [" << connfd << "] from " << peerAddr.hostNameString();

  TcpConnectionPtr conn(new TcpConnection(connfd, loop, peerAddr, _serverAddr));

  assert(_connectionMaps.find(connfd) == _connectionMaps.end());
  _connectionMaps[connfd] = conn;

  conn->setMessageCallback(_messageCallback);
  conn->setConnectionCallback(_connectionCallback);
  conn->setCloseConnectionCallback(std::bind(&TcpServer::_removeConnection, this, std::placeholders::_1));
  conn->connectEstablished();
}

说明几点:

(1)该函数只要由Acceptor中accept后新连接的回调函数;

(2)创建TcpConnection后,放入_connectionMaps中,这样TcpServer也就持有了TcpConnection,如果TcpServer不删除TcpConnection,那么TcpConnection是不会析构的;

(3)setMessageCallback,setConnectionCallback,setCloseConnectionCallback分别为设置信息接收时的用户回调,连接建立和断开时的用户回调,TcpServer连接断开回调;connectEstablished为让IO线程开始接管TcpConnection上的事件监听;


移除连接

void TcpServer::_removeConnection(const TcpConnectionPtr& conn) //thread safe
{
  _loop->queueInLoop(std::bind(&TcpServer::_removeConnectionInLoop, this, conn));
}

void TcpServer::_removeConnectionInLoop(const TcpConnectionPtr& conn)
{
  LOG_DEBUG << "use_count: " << conn.use_count();
  _connectionMaps.erase(conn->connfd());
  LOG_DEBUG << "TcpServer::_removeConnection fd[" << conn->connfd() << "] " << conn.use_count();
}

说明几点:

(1)_removeConnection为上述TcpConnection通过setCloseConnectionCallback设置的TcpServer连接断开回调,最后连接断开时,为保证线程安全性,将会在TcpServer本身的EventLoop中进行真正的删除;

【网络组件】服务器TcpServer

标签:

原文地址:http://blog.csdn.net/skyuppour/article/details/44873449

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!