您的位置:首页 > 房产 > 建筑 > 烟台网络公司哪家好_门户型网站建设_微信小程序怎么开通_批量查询指数

烟台网络公司哪家好_门户型网站建设_微信小程序怎么开通_批量查询指数

2024/12/23 2:10:11 来源:https://blog.csdn.net/2404_87273268/article/details/144445968  浏览:    关键词:烟台网络公司哪家好_门户型网站建设_微信小程序怎么开通_批量查询指数
烟台网络公司哪家好_门户型网站建设_微信小程序怎么开通_批量查询指数

文章目录

  • 前文
  • InetAddress
      • InetAddress.h
  • Socket
      • Socket.h
      • Socket.cc
  • Acceptor
      • Acceptor.h
      • Acceptor.cc

前文

重写Muduo库实现核心模块的Git仓库

注:本文将重点剖析 Muduo 网络库的核心框架,深入探讨作者精妙的代码设计思路,并针对核心代码部分进行重写,将原本依赖 boost 的实现替换为原生的 C++11 语法。需要说明的是,本文并不打算对整个 Muduo 库进行完整的重写。Muduo库源码链接

在前几篇博客中,我们已经详细讲解了以下模块:

  1. 事件循环相关模块
  • EventLoop:事件循环的核心模块,负责事件监听和分发。
  • Channel:将文件描述符与事件处理回调绑定的桥梁。
  • Poller:事件分发器的抽象基类。
  • EpollPoller:基于 epoll 的事件分发器具体实现。
  1. 线程相关模块
  • Thread:对线程的封装,提供简单易用的接口。
  • EventLoopThread:为每个 EventLoop 提供专属线程。
  • EventLoopThreadPool:线程池,管理多个 EventLoop 线程,实现负载均衡。
  1. 基础模块
  • Buffer:高效管理数据收发的缓冲区模块。
  • Timestamp:提供高精度时间戳支持。
  • Logger:日志记录模块,用于调试和运行时信息输出。

这些模块构成了 Muduo 网络库的核心基础,并在高性能网络编程中扮演着不可或缺的角色。

网络模块的解析将分为两部分进行。在本篇文章中,我们将重点讲解以下模块:

  • Socket
  • InetAddress
  • Acceptor

TcpConnectionTcpServer 这两个模块会在后续文章中进行详细解析。这两个模块是 Muduo 网络库的核心所在,对理解其设计至关重要,请大家务必关注后续内容!

InetAddress

InetAddress对IP和Port进行封装,并提供将其转化为string的方法。

类图如下所示:

image-20241213104700208

InetAddress.h

此类理解起来较为容易,故不做讲解。

class InetAddress
{
public:InetAddress() = default;InetAddress(u_int16_t port,std::string ip = "127.0.0.1");explicit InetAddress(const sockaddr_in& addr) : addr_(addr){}std::string toIp() const;std::string toIpPort() const;u_int16_t toPort() const;const sockaddr* getSockAddr() const { return (sockaddr*)&addr_; }void setSockAddr(const sockaddr_in& addr) { addr_ = addr;}
private:struct sockaddr_in addr_; 
};

Socket

Socket 对网络套接字进行了封装,提供了创建、管理和操作套接字的接口,并包含了一系列修改套接字选项的方法。此外,它还为网络编程中的常用操作(如绑定、监听、关闭等)提供了简洁易用的封装,从而简化了套接字的使用。

类图如下:

image-20241213105323660

Socket.h

class Socket : noncopyable
{
public:explicit Socket(int sockfd) : sockfd_(sockfd) {}~Socket();int fd() const { return sockfd_; }void bindAddress(const InetAddress& localaddr);    void listen();int accpet(InetAddress* peeraddr);void shutdownWrite();void setTcpNoDelay(bool on);void setReuseAddr(bool on);void setReusePort(bool on);void setKeepAlive(bool on);
private:const int sockfd_;
};

解析

setTcpNoDelay:禁止Nagle算法

setReuseAddr:允许重用本地地址

setReusePort:允许重用本地端口

setKeepAlive:周期性测试连接是否存货

Socket.cc

Socket::~Socket()
{::close(sockfd_);
}void Socket::bindAddress(InetAddress const &localaddr)
{if( 0 != ::bind(sockfd_, localaddr.getSockAddr(), sizeof(sockaddr))){LOG_FATAL("bind sockfd:%d fail", sockfd_);}
}void Socket::listen()
{if(0 != ::listen(sockfd_, 1024)){LOG_FATAL("listen sockfd:%d fail", sockfd_);}
}int Socket::accpet(InetAddress *peeraddr)
{sockaddr_in addr; socklen_t len;bzero(&addr, sizeof addr);int connfd = accept(sockfd_, (sockaddr*)&addr, &len);if(connfd >= 0){peeraddr->setSockAddr(addr);}return connfd;
}void Socket::shutdownWrite()
{if(0 != ::shutdown(sockfd_, SHUT_WR)){LOG_ERROR("shutdownWrite error ");}
}void Socket::setTcpNoDelay(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY,&optval, static_cast<socklen_t>(sizeof optval));// FIXME CHECK
}void Socket::setReuseAddr(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,&optval, static_cast<socklen_t>(sizeof optval));// FIXME CHECK
}void Socket::setReusePort(bool on)
{
#ifdef SO_REUSEPORTint optval = on ? 1 : 0;int ret = ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT,&optval, static_cast<socklen_t>(sizeof optval));if (ret < 0 && on){LOG_ERROR("SO_REUSEPORT failed.");}
#elseif (on){LOG_ERROR << "SO_REUSEPORT is not supported.";}
#endif
}void Socket::setKeepAlive(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE,&optval, static_cast<socklen_t>(sizeof optval));// FIXME CHECK
}

Acceptor

Acceptor是运行在MainLoop里负责监听并接受客户端的连接,并提供设置新连接回调函数的方法setNewConnectionCallback(const NewConnectionCallback& cb),以便客户端连接后可以调用此回调函数。类图如下:

image-20241213111537782

Acceptor.h

class Acceptor : noncopyable
{
public:using NewConnectionCallback = std::function<void(int, const InetAddress&)>;Acceptor(EventLoop* loop, const InetAddress& ListenAddr, bool reuseport);~Acceptor();void setNewConnectionCallback(const NewConnectionCallback& cb){NewConnectionCallback_ = std::move(cb);}bool listening() const { return listening_; }void listen();
private:void handleRead();EventLoop* loop_;Socket acceptSocket_;Channel acceptChannel;NewConnectionCallback NewConnectionCallback_;bool listening_;
};

解析

成员变量:

  • loop_MainLoop,主线程中的 EventLoop,负责管理和分发事件。
  • acceptSocket_:封装了监听套接字的 Socket 对象,用于接受新连接。
  • acceptChannel_:与监听套接字关联的 Channel,负责将监听套接字的事件(如新连接到来)分发到注册的回调函数中处理。

成员方法:

  • listen():开启监听套接字
  • handleRead():注册到acceptChannel的读回调函数,当有新连接到来时(读事件),执行此函数

Acceptor.cc

static int CreateNonblocking()
{int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);if(sockfd < 0){LOG_FATAL("%s:%s:%d listen socket create error:%d", __FILE__, __FUNCTION__, __LINE__, errno);}return sockfd;
}Acceptor::Acceptor(EventLoop *loop, InetAddress const &ListenAddr,bool reuseport) : loop_(loop),acceptSocket_(CreateNonblocking()),acceptChannel(loop_, acceptSocket_.fd()),listening_(false)
{acceptSocket_.setReuseAddr(true);acceptSocket_.setReusePort(true);acceptSocket_.bindAddress(ListenAddr);acceptChannel.setReadCallback(std::bind(&Acceptor::handleRead, this));
}Acceptor::~Acceptor()
{acceptChannel.disableAll();acceptChannel.remove();
}void Acceptor::listen()
{listening_ = true;acceptSocket_.listen();acceptChannel.enableReading();
}void Acceptor::handleRead()
{InetAddress peerAddr;int connfd = acceptSocket_.accpet(&peerAddr);if(connfd >= 0){if(NewConnectionCallback_){NewConnectionCallback_(connfd, peerAddr);}else{::close(connfd);}}  else{LOG_ERROR("%s:%s:%d listen socket accept error:%d", __FILE__, __FUNCTION__, __LINE__, errno);if(errno == EMFILE){LOG_ERROR("%s:%s:%d listen socket limit error:%d", __FILE__, __FUNCTION__, __LINE__, errno);}}}

到这里,InetAddressSocketAcceptor这三个模组就讲完了,这三个模块内容不多,也不难,但是是网络模块的基础部分。下一节的TcpServerTcpConnection是本系列的重中之重,请大家记得订阅!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com