总结:
InetAddress主要是对addr的操作;
Endian.h主要对本机字节序和网络字节序IP PORT进行转换的;
SocketsOps主要是基本的socket, bind ,listen ,accept, read, write, readv, getLocalAddr, getPeerAddr的调用
InetAddress.h
#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
{
///
/// 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);
/// Constructs an endpoint with given ip and port.
/// @c ip should be "1.2.3.4"
InetAddress(const StringPiece& ip, uint16_t port);
/// Constructs an endpoint with given struct @c sockaddr_in
/// Mostly used when accepting new connections
InetAddress(const struct sockaddr_in& addr)
: addr_(addr)
{ }
string toIp() const;
string toIpPort() const;
string toHostPort() const __attribute__ ((deprecated))
{ return toIpPort(); }
// default copy/assignment are Okay
const struct sockaddr_in& getSockAddrInet() const { return addr_; }
void setSockAddrInet(const struct sockaddr_in& addr) { addr_ = addr; }
uint32_t ipNetEndian() const { return addr_.sin_addr.s_addr; }
uint16_t portNetEndian() const { return addr_.sin_port; }
private:
struct sockaddr_in addr_;
};
}
}
#endif // MUDUO_NET_INETADDRESS_H
InetAddress.cpp
#include <muduo/net/InetAddress.h>
#include <muduo/net/Endian.h>
#include <muduo/net/SocketsOps.h>
#include <strings.h> // bzero
#include <netinet/in.h>
#include <boost/static_assert.hpp>
// INADDR_ANY use (type)value casting.
#pragma GCC diagnostic ignored "-Wold-style-cast"
static const in_addr_t kInaddrAny = INADDR_ANY;
#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 */
// };
using namespace muduo;
using namespace muduo::net;
BOOST_STATIC_ASSERT(sizeof(InetAddress) == sizeof(struct sockaddr_in));
//指定addr_ 为服务端
InetAddress::InetAddress(uint16_t port)
{
bzero(&addr_, sizeof addr_);
addr_.sin_family = AF_INET;
addr_.sin_addr.s_addr = sockets::hostToNetwork32(kInaddrAny);
addr_.sin_port = sockets::hostToNetwork16(port);
}
//将[string ip 和unsigned short port] 存到addr_ 中
InetAddress::InetAddress(const StringPiece& ip, uint16_t port)
{
bzero(&addr_, sizeof addr_);
sockets::fromIpPort(ip.data(), port, &addr_);
}
//将addr_ 以192.168.1.114:8000存到buf 中返回
string InetAddress::toIpPort() const
{
char buf[32];
sockets::toIpPort(buf, sizeof buf, addr_);
return buf;
}
//将addr_ 中192.168.1.114存到buf 中返回
string InetAddress::toIp() const
{
char buf[32];
sockets::toIp(buf, sizeof buf, addr_);
return buf;
}
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 __GNUC_MINOR__ >= 6
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wold-style-cast"
/*64位的ip本地字节序转为网络字节序*/
inline uint64_t hostToNetwork64(uint64_t host64)
{
return htobe64(host64);
}
/*32位的ip本地字节序转为网络字节序*/
inline uint32_t hostToNetwork32(uint32_t host32)
{
return htobe32(host32);
}
/*16位的port本地字节序转为网络字节序*/
inline uint16_t hostToNetwork16(uint16_t host16)
{
return htobe16(host16);
}
/*64位的ip网络字节序转为本地字节序*/
inline uint64_t networkToHost64(uint64_t net64)
{
return be64toh(net64);
}
/*32位的ip网络字节序转为本地字节序*/
inline uint32_t networkToHost32(uint32_t net32)
{
return be32toh(net32);
}
/*16位的port网络字节序转为本地字节序*/
inline uint16_t networkToHost16(uint16_t net16)
{
return be16toh(net16);
}
#if __GNUC_MINOR__ >= 6
#pragma GCC diagnostic pop
#else
#pragma GCC diagnostic error "-Wconversion"
#pragma GCC diagnostic error "-Wold-style-cast"
#endif
}
}
}
#endif // MUDUO_NET_ENDIAN_H
SocketsOps.h
#ifndef MUDUO_NET_SOCKETSOPS_H
#define MUDUO_NET_SOCKETSOPS_H
#include <arpa/inet.h>
namespace muduo
{
namespace net
{
namespace sockets
{
///
/// Creates a non-blocking socket file descriptor,
/// abort if any error.
int createNonblockingOrDie();
int connect(int sockfd, const struct sockaddr_in& addr);
void bindOrDie(int sockfd, const struct sockaddr_in& addr);
void listenOrDie(int sockfd);
int accept(int sockfd, struct sockaddr_in* addr);
ssize_t read(int sockfd, void *buf, size_t count);
ssize_t readv(int sockfd, const struct iovec *iov, int iovcnt);
ssize_t write(int sockfd, const void *buf, size_t count);
void close(int sockfd);
void shutdownWrite(int sockfd);
void toIpPort(char* buf, size_t size,
const struct sockaddr_in& addr);
void toIp(char* buf, size_t size,
const struct sockaddr_in& addr);
void fromIpPort(const char* ip, uint16_t port,
struct sockaddr_in* addr);
int getSocketError(int sockfd);
struct sockaddr_in getLocalAddr(int sockfd);
struct sockaddr_in getPeerAddr(int sockfd);
bool isSelfConnect(int sockfd);
}
}
}
#endif // MUDUO_NET_SOCKETSOPS_H
SocketsOps.cpp
#include <muduo/net/SocketsOps.h>
#include <muduo/base/Logging.h>
#include <muduo/base/Types.h>
#include <muduo/net/Endian.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> // snprintf
#include <strings.h> // bzero
#include <sys/socket.h>
#include <unistd.h>
using namespace muduo;
using namespace muduo::net;
namespace
{
typedef struct sockaddr SA;
/*
http://blog.csdn.net/ygm_linux/article/details/25778141
系统调用时候用的sockaddr 而不是sockaddr_in
第一个,不允许修改参数值和返回值的;
第二个,允许修改参数值和返回值的;
*/
const SA* sockaddr_cast(const struct sockaddr_in* addr)
{
return static_cast<const SA*>(implicit_cast<const void*>(addr));
}
SA* sockaddr_cast(struct sockaddr_in* addr)
{
return static_cast<SA*>(implicit_cast<void*>(addr));
}
/*
设置sockfd 非阻塞;
*/
void setNonBlockAndCloseOnExec(int sockfd)
{
// non-block
int flags = ::fcntl(sockfd, F_GETFL, 0);
flags |= O_NONBLOCK;
int ret = ::fcntl(sockfd, F_SETFL, flags);
// FIXME check
// close-on-exec
flags = ::fcntl(sockfd, F_GETFD, 0);
flags |= FD_CLOEXEC;
ret = ::fcntl(sockfd, F_SETFD, flags);
// FIXME check
(void)ret;
}
}
/*
创建sockfd 并设置为非阻塞;
*/
int sockets::createNonblockingOrDie()
{
// socket
#if VALGRIND
int sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0)
{
LOG_SYSFATAL << "sockets::createNonblockingOrDie";
}
setNonBlockAndCloseOnExec(sockfd);
#else
int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
if (sockfd < 0)
{
LOG_SYSFATAL << "sockets::createNonblockingOrDie";
}
#endif
return sockfd;
}
/*
bind addr;
*/
void sockets::bindOrDie(int sockfd, const struct sockaddr_in& addr)
{
int ret = ::bind(sockfd, sockaddr_cast(&addr), static_cast<socklen_t>(sizeof addr));
if (ret < 0)
{
LOG_SYSFATAL << "sockets::bindOrDie";
}
}
/*
http://blog.csdn.net/ygm_linux/article/details/25779311
listen;
*/
void sockets::listenOrDie(int sockfd)
{
int ret = ::listen(sockfd, SOMAXCONN);
if (ret < 0)
{
LOG_SYSFATAL << "sockets::listenOrDie";
}
}
/*
accept;
*/
int sockets::accept(int sockfd, struct sockaddr_in* addr)
{
socklen_t addrlen = static_cast<socklen_t>(sizeof *addr);
#if VALGRIND
int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen);
setNonBlockAndCloseOnExec(connfd);
#else
int connfd = ::accept4(sockfd, sockaddr_cast(addr),
&addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
#endif
if (connfd < 0)
{
int savedErrno = errno;
LOG_SYSERR << "Socket::accept";
switch (savedErrno)
{
case EAGAIN:
case ECONNABORTED:
case EINTR:
case EPROTO: // ???
case EPERM:
case EMFILE: // per-process lmit of open file desctiptor ???
// expected errors
errno = savedErrno;
break;
case EBADF:
case EFAULT:
case EINVAL:
case ENFILE:
case ENOBUFS:
case ENOMEM:
case ENOTSOCK:
case EOPNOTSUPP:
// unexpected errors
LOG_FATAL << "unexpected error of ::accept " << savedErrno;
break;
default:
LOG_FATAL << "unknown error of ::accept " << savedErrno;
break;
}
}
return connfd;
}
/*
connect;
*/
int sockets::connect(int sockfd, const struct sockaddr_in& addr)
{
return ::connect(sockfd, sockaddr_cast(&addr), static_cast<socklen_t>(sizeof addr));
}
/*
read sockfd;
*/
ssize_t sockets::read(int sockfd, void *buf, size_t count)
{
return ::read(sockfd, buf, count);
}
/*
readv sockfd; 将数据依次填到buf=iov[0]
至buf=iov[iovcnt-1]
*/
ssize_t sockets::readv(int sockfd, const struct iovec *iov, int iovcnt)
{
return ::readv(sockfd, iov, iovcnt);
}
/*
write sockfd;
*/
ssize_t sockets::write(int sockfd, const void *buf, size_t count)
{
return ::write(sockfd, buf, count);
}
void sockets::close(int sockfd)
{
if (::close(sockfd) < 0)
{
LOG_SYSERR << "sockets::close";
}
}
/*
shutdown sockfd关闭写端; 可以依然读的
*/
void sockets::shutdownWrite(int sockfd)
{
if (::shutdown(sockfd, SHUT_WR) < 0)
{
LOG_SYSERR << "sockets::shutdownWrite";
}
}
/*
addr ==>192.168.1.114:8000
*/
void sockets::toIpPort(char* buf, size_t size,
const struct sockaddr_in& addr)
{
char host[INET_ADDRSTRLEN] = "INVALID";
toIp(host, sizeof host, addr);
uint16_t port = sockets::networkToHost16(addr.sin_port);
snprintf(buf, size, "%s:%u", host, port);
}
/*
addr ==>192.168.1.114
*/
void sockets::toIp(char* buf, size_t size,
const struct sockaddr_in& addr)
{
assert(size >= INET_ADDRSTRLEN);
::inet_ntop(AF_INET, &addr.sin_addr, buf, static_cast<socklen_t>(size));
}
/*
"192.168.1.114" 8000==>addr
*/
void sockets::fromIpPort(const char* ip, uint16_t port,
struct sockaddr_in* addr)
{
addr->sin_family = AF_INET;
addr->sin_port = hostToNetwork16(port);
if (::inet_pton(AF_INET, ip, &addr->sin_addr) <= 0)
{
LOG_SYSERR << "sockets::fromIpPort";
}
}
/*
http://blog.csdn.net/ygm_linux/article/details/25781097
可以利用printf("%s\n", strerror(errno));
知道为何出错
*/
int sockets::getSocketError(int sockfd)
{
int optval;
socklen_t optlen = static_cast<socklen_t>(sizeof optval);
if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0)
{
return errno;
}
else
{
return optval;
}
}
/*
利用sockfd 获得本机localaddr
*/
struct sockaddr_in sockets::getLocalAddr(int sockfd)
{
struct sockaddr_in localaddr;
bzero(&localaddr, sizeof localaddr);
socklen_t addrlen = static_cast<socklen_t>(sizeof localaddr);
if (::getsockname(sockfd, sockaddr_cast(&localaddr), &addrlen) < 0)
{
LOG_SYSERR << "sockets::getLocalAddr";
}
return localaddr;
}
/*
利用sockfd 获得对端peeraddr
*/
struct sockaddr_in sockets::getPeerAddr(int sockfd)
{
struct sockaddr_in peeraddr;
bzero(&peeraddr, sizeof peeraddr);
socklen_t addrlen = static_cast<socklen_t>(sizeof peeraddr);
if (::getpeername(sockfd, sockaddr_cast(&peeraddr), &addrlen) < 0)
{
LOG_SYSERR << "sockets::getPeerAddr";
}
return peeraddr;
}
/*
利用sockfd 判断是否本机既做客户端又做服务端
*/
bool sockets::isSelfConnect(int sockfd)
{
struct sockaddr_in localaddr = getLocalAddr(sockfd);
struct sockaddr_in peeraddr = getPeerAddr(sockfd);
return localaddr.sin_port == peeraddr.sin_port
&& localaddr.sin_addr.s_addr == peeraddr.sin_addr.s_addr;
}