【muduo网络库学习】之Acceptor类分析

《Linux多线程服务端编程》一书的8.4节介绍了Acceptor类的实现,下面是对这个类的分析。

首先从client端入手看看怎么来使用这个类,client的程序如下:

#include "Acceptor.h"
#include "EventLoop.h"
#include "InetAddress.h"
#include "SocketsOps.h"
#include <stdio.h>

void newConnection(int sockfd, const muduo::InetAddress& peerAddr)
{
  printf("newConnection(): accepted a new connection from %s\n",
         peerAddr.toHostPort().c_str());
  ::write(sockfd, "How are you?\n", 13);
  muduo::sockets::close(sockfd);
}

int main()
{
  printf("main(): pid = %d\n", getpid());

  muduo::InetAddress listenAddr(9981);
  muduo::EventLoop loop;

  muduo::Acceptor acceptor(&loop, listenAddr);
  acceptor.setNewConnectionCallback(newConnection);
  acceptor.listen();

  loop.loop();
}
muduo::InetAddress listenAddr(9981)是定义一个类用于描述要监听的端口。这个类比较简单,其私有成员变量就是  struct sockaddr_in addr_。可知这个类就是对linux C里面的sockaddr_in做了进一步的封装,以体现C++程序的封装性和提高代码的可读性。

接下来看看

  muduo::Acceptor acceptor(&loop, listenAddr);
这会调用Acceptor类的构造函数,如下:

Acceptor::Acceptor(EventLoop* loop, const InetAddress& listenAddr)
  : loop_(loop),
    acceptSocket_(sockets::createNonblockingOrDie()),
    acceptChannel_(loop, acceptSocket_.fd()),
    listenning_(false)
{
  acceptSocket_.setReuseAddr(true);
  acceptSocket_.bindAddress(listenAddr);
  acceptChannel_.setReadCallback(
      boost::bind(&Acceptor::handleRead, this));
}

如上所示,在构造函数里面,会完成socket的create(sockets::createNonblockingOrDie()),socket的bind(acceptSocket_.bindAddress(listenAddr);)等等准备工作,这根UNV中TCP server需要调用的socket(),bind()等函数是一致的。同时,构造函数里面还会调用初始化好acceptChannel_,并且为acceptChannel设置相应的回调函数。在完成了这些工作之后,这个socket对应的fd,channel就都已经准备好了。

再接下来是

  acceptor.setNewConnectionCallback(newConnection);
  acceptor.listen();
第一个setNewConnectionCallback比较简单,就是在accept完一个TCP连接之后,会对应到这个回调函数里面去完成一些业务逻辑。注意这里的回调函数不同于上一步中的
boost::bind(&Acceptor::handleRead
上一步中的这个回调函数实际上是会在loop循环中调用,所完成的还是底层的accept工作。而setNewConnectionCallback这个回调函数是在accept成功之后才会去调用。

至于acceptor.listen(),其程序如下:

void Acceptor::listen()
{
  loop_->assertInLoopThread();
  listenning_ = true;
  acceptSocket_.listen();
  acceptChannel_.enableReading();
}

上述程序也很好理解,就是完成了listen()系统调用,并且通过enableReading将accept_channel加到poll数组中

接下来就是调用

  loop.loop();
进入loop循环,当有连接到来的时候, 程序会从poll中跳出,然后对应到accept_channel的回调函数中来使用accept系统调用接收请求。在接收完请求之后会调用客户端定义的newConnection回调函数。

从以上程序可知,在使用像muduo这样的网络库时候,比较核心的其实是回调函数的编写。底层的相关操作都是由网络库封装好的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值