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;
}
}