【网络组件】服务器TcpServer

本节研究服务器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中进行真正的删除;

时间: 2024-10-06 01:19:18

【网络组件】服务器TcpServer的相关文章

【重磅】移动网络性能揭秘(上)--移动网络组件详解

简介 在过去的几年里我们在移动蜂窝网络性能方面取得了重大进展.但是由于网络延迟的膨胀导致许多应用并没有得到改善. 延迟问题长期以来一直制约着移动网络.尽管近年来已取得一些进展,但减少网络延迟没有跟上延迟的增长速度.正是由于这种不对等导致了延迟,而不是吞吐量,成为影响网络性能的最大因素. 这篇文章逻辑上主要包含两章.第一部分将讨论导致移动网络延迟的细节:第二部分介绍提高网络性能降低延迟的软件技术. 你在等待的是什么? 延迟表示一个数据包通过一个或一系列网络所需要的时间.由于很多因素,移动网络会使已

openstack M 版 neutron网络组件基础入门

在我们openstack学习当中,网络组件neutron无疑是令很多人很难理解的,可以说要深入理解 了neutron组件,你基本完成了openstack 60%的学习,存储方面只要不涉及到分布式,剩下的基本都比较简单了 相信很多人第一次看到这种图的时候都会被吓一跳,没错,这就是openstack  neutron组件里面涉及到的数据流程,里面涉及到的知识点很多很多 Openstack网络模型中的几个概念网络: Management Network: 管理网络,连接所有节点. External N

网络策略服务器

TechNet 库 Windows Server Windows Server 2008 R2 und Windows Server 2008 按类别提供的 Windows Server 内容 按类别提供的 Windows Server 2008 R2 内容 已安装的 Windows Server 2008 R2 产品帮助 Network Policy and Access Services 网络策略服务器 网络策略服务器概述 NPS 和防火墙 NPS 模板 NPS 中的策略 在 Active

iOS 对比网络组件:AFNetworking 与 ASIHTTPRequest

在开发iOS应用过程中,如何高效的与服务端API进行数据交换,是一个常见问题.一般开发者都会选择一个第三方的网络组件作为服务,以提高开发效率和稳定性.这些组件把复杂的网络底层操作封装成友好的类和方法,并且加入异常处理等. 那么,大家最常用的组件是什么?这些组件是如何提升开发效率和稳定性的?哪一款组件适合自己,是 AFNetworking(AFN)还是 ASIHTTPRequest(ASI)?几乎每一个iOS互联网应用开发者都会面对这样的选择题,要从这两个最常用的组件里选出一个好的还真不是那么容易

对比iOS网络组件:AFNetworking VS ASIHTTPRequest

对比iOS网络组件:AFNetworking VS ASIHTTPRequest 在开发iOS应用过程中,如何高效的与服务端API进行数据交换,是一个常见问题.一般开发者都会选择一个第三方的网络组件作为服务,以提高开发效率和稳定性.这些组件把复杂的网络底层操作封装成友好的类和方法,并且加入异常处理等. 那么,大家最常用的组件是什么?这些组件是如何提升开发效率和稳定性的?哪一款组件适合自己,是 AFNetworking(AFN)还是 ASIHTTPRequest(ASI)?几乎每一个iOS互联网应

对比iOS网络组件:AFNetworking VS ASIHTTPRequest(转载)

在开发iOS应用过程中,如何高效的与服务端API进行数据交换,是一个常见问题.一般开发者都会选择一个第三方的网络组件作为服务,以提高开发效率和稳定性.这些组件把复杂的网络底层操作封装成友好的类和方法,并且加入异常处理等. 那么,大家最常用的组件是什么?这些组件是如何提升开发效率和稳定性的?哪一款组件适合自己,是 AFNetworking(AFN)还是 ASIHTTPRequest(ASI)?几乎每一个iOS互联网应用开发者都会面对这样的选择题,要从这两个最常用的组件里选出一个好的还真不是那么容易

(转)很客观的对比iOS网络组件:AFNetworking VS ASIHTTPRequest

在开发iOS应用过程中,如何高效的与服务端API进行数据交换,是一个常见问题.一般开发者都会选择一个第三方的网络组件作为服务,以提高开发效率和稳定性.这些组件把复杂的网络底层操作封装成友好的类和方法,并且加入异常处理等. 那么,大家最常用的组件是什么?这些组件是如何提升开发效率和稳定性的?哪一款组件适合自己,是 AFNetworking(AFN)还是 ASIHTTPRequest(ASI)?几乎每一个iOS互联网应用开发者都会面对这样的选择题,要从这两个最常用的组件里选出一个好的还真不是那么容易

Flannel网络组件部署

在部署K8S之前,需要在集群服务器上部署CNI容器网络组件,从而实现集群的网络互联互通.目前可选的组件比较多,例如flannel.calico.weave等,各容器网络组件对比可参考文档:http://dockone.io/article/2599 本文介绍flannel网络组件的部署,配置环境在完成前文etcd集群和tls认证配置后.一.生成flannel证书文件 # mkdir flanneld # cd flanneld # cat flanneld-csr.json { "CN"

kubernetes 网络组件简介

链接地址:https://blog.csdn.net/kjh2007abc/article/details/86751730 k8s的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中.这是因为k8s出自Google,而在GCE里面是提供了网络模型作为基础设施的,所以k8s就假定这个网络已经存在.而在大家私有的平台设施里搭建k8s集群,就不能假定这种网络已经存在了.我们需要自己实现这个网络,将不同节点上的Docker容器之间的互相访问先打通,然后运行k8s. 目前已经有多个开源组件支