muduo源码剖析之InetAddress

简介: InetAddress 类在 muduo 网络库中被广泛使用,用于表示网络中的通信实体的地址信息,例如服务器地址、客户端地址等。通过 InetAddress 类,我们可以方便地操作 IP 地址和端口号,实现网络通信的功能。InetAddress 类是 muduo 网络库中的一个重要类,用于表示网络中的 IP 地址和端口号。源码比较简单,已经编写详细注释。

InetAddress

InetAddress 类是 muduo 网络库中的一个重要类,用于表示网络中的 IP 地址和端口号。

InetAddress 类在 muduo 网络库中被广泛使用,用于表示网络中的通信实体的地址信息,例如服务器地址、客户端地址等。通过 InetAddress 类,我们可以方便地操作 IP 地址和端口号,实现网络通信的功能。

源码比较简单,已经编写详细注释

源码剖析

InetAddress.h

// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)
//
// This is a public header file, it must only include public header files.

#ifndef MUDUO_NET_INETADDRESS_H
#define MUDUO_NET_INETADDRESS_H

#include "muduo/base/copyable.h"
#include "muduo/base/StringPiece.h"

#include <netinet/in.h>

namespace muduo
{
   
namespace net
{
   
namespace sockets
{
   
const struct sockaddr* sockaddr_cast(const struct sockaddr_in6* addr);
}

///
/// Wrapper of sockaddr_in.
///
/// This is an POD interface class.
class InetAddress : public muduo::copyable
{
   
 public:
  /// Constructs an endpoint with given port number.
  /// Mostly used in TcpServer listening.
  explicit InetAddress(uint16_t port = 0, bool loopbackOnly = false, bool ipv6 = false);

  /// Constructs an endpoint with given ip and port.
  /// @c ip should be "1.2.3.4"
  InetAddress(StringArg ip, uint16_t port, bool ipv6 = false);

  /// Constructs an endpoint with given struct @c sockaddr_in
  /// Mostly used when accepting new connections
  explicit InetAddress(const struct sockaddr_in& addr)
    : addr_(addr)
  {
    }

  explicit InetAddress(const struct sockaddr_in6& addr)
    : addr6_(addr)
  {
    }
  //返回addr_地址成员变量的协议族
  sa_family_t family() const {
    return addr_.sin_family; }

  //获取ip地址的点十分进制的字符串
  string toIp() const;

  //获取ip地址和port端口的点十分进制的字符串
  string toIpPort() const;

  //获取端口号(本机字节序)
  uint16_t port() const;

  // default copy/assignment are Okay
  //返回sockaddr结构体指针
  const struct sockaddr* getSockAddr() const {
    return sockets::sockaddr_cast(&addr6_); }

  //设置SockAddr
  void setSockAddrInet6(const struct sockaddr_in6& addr6) {
    addr6_ = addr6; }

  //获取ip地址(网络字节序)
  uint32_t ipv4NetEndian() const;

  //获取端口号(网络字节序)
  uint16_t portNetEndian() const {
    return addr_.sin_port; }

  // resolve hostname to IP address, not changing port or sin_family
  // return true on success.
  // thread safe
  //通过主机名解析出ip地址
  static bool resolve(StringArg hostname, InetAddress* result);
  // static std::vector<InetAddress> resolveAll(const char* hostname, uint16_t port = 0);

  // set IPv6 ScopeID
  //设置ipv6地址的作用域范围。
  void setScopeId(uint32_t scope_id);

 private:
  union
  {
   
    //ipv4
    struct sockaddr_in addr_;
    //ipv6
    struct sockaddr_in6 addr6_;
  };
};

}  // namespace net
}  // namespace muduo

#endif  // MUDUO_NET_INETADDRESS_H

InetAddress.cc

// Copyright 2010, Shuo Chen.  All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.

// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include "muduo/net/InetAddress.h"

#include "muduo/base/Logging.h"
#include "muduo/net/Endian.h"
#include "muduo/net/SocketsOps.h"

#include <netdb.h>
#include <netinet/in.h>

// INADDR_ANY use (type)value casting.
#pragma GCC diagnostic ignored "-Wold-style-cast"
static const in_addr_t kInaddrAny = INADDR_ANY;
static const in_addr_t kInaddrLoopback = INADDR_LOOPBACK;
#pragma GCC diagnostic error "-Wold-style-cast"

//     /* Structure describing an Internet socket address.  */
//     struct sockaddr_in {
   
//         sa_family_t    sin_family; /* address family: AF_INET */
//         uint16_t       sin_port;   /* port in network byte order */
//         struct in_addr sin_addr;   /* internet address */
//     };

//     /* Internet address. */
//     typedef uint32_t in_addr_t;
//     struct in_addr {
   
//         in_addr_t       s_addr;     /* address in network byte order */
//     };

//     struct sockaddr_in6 {
   
//         sa_family_t     sin6_family;   /* address family: AF_INET6 */
//         uint16_t        sin6_port;     /* port in network byte order */
//         uint32_t        sin6_flowinfo; /* IPv6 flow information */
//         struct in6_addr sin6_addr;     /* IPv6 address */
//         uint32_t        sin6_scope_id; /* IPv6 scope-id */
//     };

using namespace muduo;
using namespace muduo::net;

static_assert(sizeof(InetAddress) == sizeof(struct sockaddr_in6),
              "InetAddress is same size as sockaddr_in6");
static_assert(offsetof(sockaddr_in, sin_family) == 0, "sin_family offset 0");
static_assert(offsetof(sockaddr_in6, sin6_family) == 0, "sin6_family offset 0");
static_assert(offsetof(sockaddr_in, sin_port) == 2, "sin_port offset 2");
static_assert(offsetof(sockaddr_in6, sin6_port) == 2, "sin6_port offset 2");

InetAddress::InetAddress(uint16_t portArg, bool loopbackOnly, bool ipv6)
{
   
  static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0");
  static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0");
  if (ipv6)
  {
   
    memZero(&addr6_, sizeof addr6_);
    addr6_.sin6_family = AF_INET6;
    in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any;
    addr6_.sin6_addr = ip;
    addr6_.sin6_port = sockets::hostToNetwork16(portArg);
  }
  else
  {
   
    memZero(&addr_, sizeof addr_);
    addr_.sin_family = AF_INET;
    in_addr_t ip = loopbackOnly ? kInaddrLoopback : kInaddrAny;
    addr_.sin_addr.s_addr = sockets::hostToNetwork32(ip);
    addr_.sin_port = sockets::hostToNetwork16(portArg);
  }
}

InetAddress::InetAddress(StringArg ip, uint16_t portArg, bool ipv6)
{
   
  if (ipv6 || strchr(ip.c_str(), ':'))
  {
   
    memZero(&addr6_, sizeof addr6_);
    sockets::fromIpPort(ip.c_str(), portArg, &addr6_);
  }
  else
  {
   
    memZero(&addr_, sizeof addr_);
    sockets::fromIpPort(ip.c_str(), portArg, &addr_);
  }
}

string InetAddress::toIpPort() const
{
   
  char buf[64] = "";
  sockets::toIpPort(buf, sizeof buf, getSockAddr());
  return buf;
}

string InetAddress::toIp() const
{
   
  char buf[64] = "";
  sockets::toIp(buf, sizeof buf, getSockAddr());
  return buf;
}

uint32_t InetAddress::ipv4NetEndian() const
{
   
  assert(family() == AF_INET);
  return addr_.sin_addr.s_addr;
}

uint16_t InetAddress::port() const
{
   
  return sockets::networkToHost16(portNetEndian());
}

static __thread char t_resolveBuffer[64 * 1024];

bool InetAddress::resolve(StringArg hostname, InetAddress* out)
{
   
  assert(out != NULL);
  struct hostent hent;
  struct hostent* he = NULL;
  int herrno = 0;
  memZero(&hent, sizeof(hent));

  //通过主机名解析出ip地址
  int ret = gethostbyname_r(hostname.c_str(), &hent, t_resolveBuffer, sizeof t_resolveBuffer, &he, &herrno);
  if (ret == 0 && he != NULL)
  {
   
    assert(he->h_addrtype == AF_INET && he->h_length == sizeof(uint32_t));
    out->addr_.sin_addr = *reinterpret_cast<struct in_addr*>(he->h_addr);
    return true;
  }
  else
  {
   
    if (ret)
    {
   
      LOG_SYSERR << "InetAddress::resolve";
    }
    return false;
  }
}

void InetAddress::setScopeId(uint32_t scope_id)
{
   
  if (family() == AF_INET6)
  {
   
    addr6_.sin6_scope_id = scope_id;
  }
}
目录
相关文章
|
7月前
muduo源码剖析之Socket类
封装了一个sockfd相关的设置。比较简单,已经编写注释。
62 0
|
7月前
|
API
muduo源码剖析之SocketOps类
对socket设置API的封装。比较简单,已经编写注释。
45 0
|
7月前
muduo源码剖析之Acceptor监听类
Acceptor类用于创建套接字,设置套接字选项,调用socket()->bind()->listen()->accept()函数,接受连接,然后调用TcpServer设置的connect事件的回调。listen()//在TcpServer::start中调用封装了一个listen fd相关的操作,用于mainLoop接受器封装,实质上就是对Channel的多一层封装监听连接 当新连接进入时,调用Socket::accept创建套接字,触发TcpServer的回调TcpServer通过该接口设置回调,
57 0
|
7月前
muduo源码剖析之Connector客户端连接类
Connector负责主动发起连接,不负责创建socket,只负责连接的建立,外部调用Connector::start就可以发起连接,Connector具有重连的功能和停止连接的功能,连接成功建立后返回到TcpClient。
61 0
|
7月前
Muduo类详解之Poller
Muduo类详解之Poller
|
7月前
Muduo类详解之EventLoop
Muduo类详解之EventLoop
|
7月前
|
设计模式 前端开发 数据安全/隐私保护
网络编程的魔法师:探索Netty中Handler的奇妙世界
网络编程的魔法师:探索Netty中Handler的奇妙世界
76 0
|
7月前
|
安全 C++ 容器
muduo源码剖析之TimerQueue类
通过timerfd实现的定时器功能,为EventLoop扩展了一系列runAt,runEvery,runEvery等函数TimerQueue中通过std::set维护所有的Timer,也可以使用优先队列实现muduo的TimerQueue是基于timerfd_create实现,这样超时很容易和epoll结合起来。等待超时事件保存在set集合中,注意set集合的有序性,从小到大排列,整个对TimerQueue的处理也就是对set集合的操作。
55 0
muduo源码剖析之TimerQueue类
|
7月前
|
Java 容器
muduo源码剖析之TcpServer服务端
TcpServer拥有Acceptor类,新连接到达时new TcpConnection后续客户端和TcpConnection类交互。TcpServer管理连接和启动线程池,用Acceptor接受连接。服务端封装 - muduo的server端维护了多个tcpconnection注意TcpServer本身不带Channel,而是使用Acceptor的Channel。
79 0
muduo源码剖析之TcpServer服务端
|
7月前
|
网络协议
muduo源码剖析之TcpClient客户端类
muduo用TcpClient发起连接,TcpClient有一个Connector连接器,TCPClient使用Conneccor发起连接, 连接建立成功后, 用socket创建TcpConnection来管理连接, 每个TcpClient class只管理一个TcpConnecction,连接建立成功后设置相应的回调函数。很显然,TcpClient用来管理客户端连接,真正连接交给Connector。
95 0
muduo源码剖析之TcpClient客户端类