Muduo网络库源码分析之对socket及其相关操作的封装

本文详细分析了Muduo网络库中关于socket的操作,包括字节序转换、Socket类的封装,如绑定地址、监听、接受连接等。此外,还介绍了InetAddress类对套接字地址的封装,以及SocketsOps类对socket相关操作的封装。建议读者了解TCP套接字编程和套接字选项知识。
摘要由CSDN通过智能技术生成

主要涉及到的类和实现文件有:

  1. Endian.h
    提供了字节序转换的函数。
  2. Socket.h/Socket.cc
    socketfd 的封装,提供了绑定地址、开始listen、接受连接等操作,并可设置套接字选项。
  3. InetAddress.h/InetAddress.cc
    套接字地址的封装,提供了多种方式初始化一个地址,还提供方法从地址中拿到 ip 和 port。
  4. SocketsOps.h/SocketsOps.cc
    封装了 socket 相关的一些操作,提供给 Socket 和 InetAddress 用。

这部分就是基本的 TCP 套接字编程和套接字选项的知识,代码逻辑也很简单,推荐看下 UNP卷一 的相关章节。

下面逐一看下这几个相关的文件。

字节序转换部分(Endian.h)

#ifndef MUDUO_NET_ENDIAN_H
#define MUDUO_NET_ENDIAN_H

#include <stdint.h>
#include <endian.h>

namespace muduo
{
   
namespace net
{
   
namespace sockets
{
   

// the inline assembler code makes type blur,
// so we disable warnings for a while.
#if defined(__clang__) || __GNUC_PREREQ (4,6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wold-style-cast"

/* uint64_t 的整形数字由机器字节序转化为网络字节序 */
inline uint64_t hostToNetwork64(uint64_t host64)
{
  return htobe64(host64);
}

/* uint32_t 的整形数字由机器字节序转化为网络字节序 */
inline uint32_t hostToNetwork32(uint32_t host32)
{
  return htobe32(host32);
}

/* uint16_t 的整形数字由机器字节序转化为网络字节序 */
inline uint16_t hostToNetwork16(uint16_t host16)
{
  return htobe16(host16);
}

/* uint64_t 的整形数字由网络字节序转化为机器字节序 */
inline uint64_t networkToHost64(uint64_t net64)
{
  return be64toh(net64);
}

/* uint32_t 的整形数字由网络字节序转化为机器字节序 */
inline uint32_t networkToHost32(uint32_t net32)
{
  return be32toh(net32);
}

/* uint16_t 的整形数字由网络字节序转化为机器字节序 */
inline uint16_t networkToHost16(uint16_t net16)
{
  return be16toh(net16);
}
#if defined(__clang__) || __GNUC_PREREQ (4,6)
#pragma GCC diagnostic pop
#else
#pragma GCC diagnostic warning "-Wconversion"
#pragma GCC diagnostic warning "-Wold-style-cast"
#endif
}
}
}

#endif  // MUDUO_NET_ENDIAN_H

Socket

Socket.h

#ifndef MUDUO_NET_SOCKET_H
#define MUDUO_NET_SOCKET_H

#include <boost/noncopyable.hpp>

// struct tcp_info is in <netinet/tcp.h>
struct tcp_info;

namespace muduo
{
///
/// TCP networking.
///
namespace net
{

class InetAddress;

/// It closes the sockfd when desctructs.
/* sock 描述符 fd的封装,实现了 绑定了地址,开始监听 并接受连接 */
class Socket : boost::noncopyable
{
 public:
  explicit Socket(int sockfd)
    : sockfd_(sockfd)
  { }

  /* close(sockfd_) */
  ~Socket();

  /* 返回 这个 socket 的 fd*/
  int fd() const { return sockfd_; }

  /* 获取与这个套接字相关联的选项,成功返回 true */
  bool getTcpInfo(struct tcp_info*) const;
  bool getTcpInfoString(char* buf, int len) const;

  /* 调用bind,绑定sockaddr */
  void bindAddress(const InetAddress& localaddr);
  /* 调用listen ,开始监听*/
  void listen();

  /// On success, returns a non-negative integer that is
  /// a descriptor for the accepted socket, which has been
  /// set to non-blocking and close-on-exec. *peeraddr is assigned.
  /// On error, -1 is returned, and *peeraddr is untouched.
  /* 调用accept,成功返回non-blocking和close-on-exec属性的 connfd */
  int accept(InetAddress* peeraddr);

  /* 关闭"写"方向的连接 */
  void shutdownWrite();


  /* 是否使用 Nagle 算法 */
  void setTcpNoDelay(bool on);

  /* 是否重用本地地址 */
  void setReuseAddr(bool on);

  /* 是否重用本地端口 */
  void setReusePort(bool on);

  /* 是否定期检测连接数否存在 */
  void setKeepAlive(bool on);

 private:
  const int sockfd_; // sockket fd
};

}
}
#endif  // MUDUO_NET_SOCKET_H

Socket.cc

#include <muduo/net/Socket.h>

#include <muduo/base/Logging.h>
#include <muduo/net/InetAddress.h>
#include <muduo/net/SocketsOps.h>

#include <netinet/in.h>
#include <netinet/tcp.h>
#include <strings.h>  // bzero
#include <stdio.h>  // snprintf

using namespace muduo;
using namespace muduo::net;

/* 析构时关闭 fd */
Socket::~Socket()
{
  sockets::close(sockfd_);
}


bool Socket::getTcpInfo(struct tcp_info* tcpi) const
{
  socklen_t len = sizeof(*tcpi);
  bzero(tcpi, len);
  return ::getsockopt(sockfd_, SOL_TCP, TCP_INFO, tcpi, &len) == 0;
}

/* 将TCP信息转化为字符串 */
bool Socket::getTcpInfoString(char* buf, int len) const
{
  struct tcp_info tcpi;
  bool ok = getTcpInfo(&tcpi);
  if (ok)
  {
    snprintf(buf, len, "unrecovered=%u "
             "rto=%u ato=%u snd_mss=%u rcv_mss=%u "
             "lost=%u retrans=%u rtt=%u rttvar=%u "
             "sshthresh=%u cwnd=%u total_retrans=%u",
             tcpi.tcpi_retransmits,  // Number of unrecovered [RTO] timeouts
             tcpi.tcpi_rto,          // Retransmit timeout in usec
             tcpi.tcpi_ato,          // Predicted tick of soft clock in usec
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值