muduo源码剖析之SocketOps类

编程入门 行业动态 更新时间:2024-10-25 18:36:32

muduo<a href=https://www.elefans.com/category/jswz/34/1770099.html style=源码剖析之SocketOps类"/>

muduo源码剖析之SocketOps类

SocketOps

对socket设置API的封装

比较简单,已经编写注释

// Copyright 2010, Shuo Chen.  All rights reserved.
// /
//
// 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 an internal header file, you should not include this.#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.
//创建一个非阻塞的socket
int createNonblockingOrDie(sa_family_t family);//调用socket的connect函数连接服务端
int  connect(int sockfd, const struct sockaddr* addr);//调用socket的bind函数绑定
void bindOrDie(int sockfd, const struct sockaddr* addr);//调用socket套接字的listrn函数
void listenOrDie(int sockfd);//接收一个连接并设置非阻塞
int  accept(int sockfd, struct sockaddr_in6* addr);//调用socket套接字read函数
ssize_t read(int sockfd, void *buf, size_t count);//调用socket套接字readv函数(分块读)
ssize_t readv(int sockfd, const struct iovec *iov, int iovcnt);//调用socket套接字write函数
ssize_t write(int sockfd, const void *buf, size_t count);//调用socket套接字close关闭套接字函数
void close(int sockfd);//调用shutdown函数优雅关闭写端
void shutdownWrite(int sockfd);//将将addr参数中的ip地址转换为点分十进制的字符串,
//并获取port端口号,
//将数据写入buf参数
void toIpPort(char* buf, size_t size,const struct sockaddr* addr);//将addr参数中的ip地址转换为点分十进制的字符串写入buf参数
void toIp(char* buf, size_t size,const struct sockaddr* addr);//这是ipv4/ipv6版本
//将ip和port赋值给addr
void fromIpPort(const char* ip, uint16_t port,struct sockaddr_in* addr);
void fromIpPort(const char* ip, uint16_t port,struct sockaddr_in6* addr);//获取当前套接口的错误状态
int getSocketError(int sockfd);//sockaddr结构体转换函数
const struct sockaddr* sockaddr_cast(const struct sockaddr_in* addr);
const struct sockaddr* sockaddr_cast(const struct sockaddr_in6* addr);
struct sockaddr* sockaddr_cast(struct sockaddr_in6* addr);
const struct sockaddr_in* sockaddr_in_cast(const struct sockaddr* addr);
const struct sockaddr_in6* sockaddr_in6_cast(const struct sockaddr* addr);//获取本地或者远程的套接字地址信息,包括远程 IP 地址和端口号
struct sockaddr_in6 getLocalAddr(int sockfd);
struct sockaddr_in6 getPeerAddr(int sockfd);//判断是不是本地连接
bool isSelfConnect(int sockfd);}  // namespace sockets
}  // namespace net
}  // namespace muduo#endif  // MUDUO_NET_SOCKETSOPS_H
// Copyright 2010, Shuo Chen.  All rights reserved.
// /
//
// 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/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 <sys/socket.h>
#include <sys/uio.h>  // readv
#include <unistd.h>using namespace muduo;
using namespace muduo::net;namespace
{typedef struct sockaddr SA;#if VALGRIND || defined (NO_ACCEPT4)
void setNonBlockAndCloseOnExec(int sockfd)
{// non-blockint flags = ::fcntl(sockfd, F_GETFL, 0);flags |= O_NONBLOCK;int ret = ::fcntl(sockfd, F_SETFL, flags);// FIXME check// close-on-execflags = ::fcntl(sockfd, F_GETFD, 0);flags |= FD_CLOEXEC;ret = ::fcntl(sockfd, F_SETFD, flags);// FIXME check(void)ret;
}
#endif}  // namespaceconst struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in6* addr)
{return static_cast<const struct sockaddr*>(implicit_cast<const void*>(addr));
}struct sockaddr* sockets::sockaddr_cast(struct sockaddr_in6* addr)
{return static_cast<struct sockaddr*>(implicit_cast<void*>(addr));
}const struct sockaddr* sockets::sockaddr_cast(const struct sockaddr_in* addr)
{return static_cast<const struct sockaddr*>(implicit_cast<const void*>(addr));
}const struct sockaddr_in* sockets::sockaddr_in_cast(const struct sockaddr* addr)
{return static_cast<const struct sockaddr_in*>(implicit_cast<const void*>(addr));
}const struct sockaddr_in6* sockets::sockaddr_in6_cast(const struct sockaddr* addr)
{return static_cast<const struct sockaddr_in6*>(implicit_cast<const void*>(addr));
}int sockets::createNonblockingOrDie(sa_family_t family)
{
#if VALGRIND//创建一个socketint sockfd = ::socket(family, SOCK_STREAM, IPPROTO_TCP);if (sockfd < 0){LOG_SYSFATAL << "sockets::createNonblockingOrDie";}//设置socket为非阻塞setNonBlockAndCloseOnExec(sockfd);
#elseint sockfd = ::socket(family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);if (sockfd < 0){LOG_SYSFATAL << "sockets::createNonblockingOrDie";}
#endifreturn sockfd;
}void sockets::bindOrDie(int sockfd, const struct sockaddr* addr)
{int ret = ::bind(sockfd, addr, static_cast<socklen_t>(sizeof(struct sockaddr_in6)));if (ret < 0){LOG_SYSFATAL << "sockets::bindOrDie";}
}void sockets::listenOrDie(int sockfd)
{int ret = ::listen(sockfd, SOMAXCONN);if (ret < 0){LOG_SYSFATAL << "sockets::listenOrDie";}
}int sockets::accept(int sockfd, struct sockaddr_in6* addr)
{socklen_t addrlen = static_cast<socklen_t>(sizeof *addr);
#if VALGRIND || defined (NO_ACCEPT4)int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen);setNonBlockAndCloseOnExec(connfd);
#elseint connfd = ::accept4(sockfd, sockaddr_cast(addr),&addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
#endifif (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 errorserrno = savedErrno;break;case EBADF:case EFAULT:case EINVAL:case ENFILE:case ENOBUFS:case ENOMEM:case ENOTSOCK:case EOPNOTSUPP:// unexpected errorsLOG_FATAL << "unexpected error of ::accept " << savedErrno;break;default:LOG_FATAL << "unknown error of ::accept " << savedErrno;break;}}return connfd;
}int sockets::connect(int sockfd, const struct sockaddr* addr)
{return ::connect(sockfd, addr, static_cast<socklen_t>(sizeof(struct sockaddr_in6)));
}ssize_t sockets::read(int sockfd, void *buf, size_t count)
{return ::read(sockfd, buf, count);
}ssize_t sockets::readv(int sockfd, const struct iovec *iov, int iovcnt)
{return ::readv(sockfd, iov, iovcnt);
}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";}
}void sockets::shutdownWrite(int sockfd)
{if (::shutdown(sockfd, SHUT_WR) < 0){LOG_SYSERR << "sockets::shutdownWrite";}
}void sockets::toIpPort(char* buf, size_t size,const struct sockaddr* addr)
{//如果ip是ipv6if (addr->sa_family == AF_INET6){buf[0] = '[';//先转换ip地址toIp(buf+1, size-1, addr);size_t end = ::strlen(buf);const struct sockaddr_in6* addr6 = sockaddr_in6_cast(addr);//将端口号从网络字节序转换为本机字节序,再将其写人bufuint16_t port = sockets::networkToHost16(addr6->sin6_port);assert(size > end);snprintf(buf+end, size-end, "]:%u", port);return;}//如果走到这里,那么这是一个ipv4//先转换ip地址toIp(buf, size, addr);size_t end = ::strlen(buf);const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);//将端口号从网络字节序转换为本机字节序,再将其写人bufuint16_t port = sockets::networkToHost16(addr4->sin_port);assert(size > end);snprintf(buf+end, size-end, ":%u", port);
}void sockets::toIp(char* buf, size_t size,const struct sockaddr* addr)
{//判断ipv4if (addr->sa_family == AF_INET){assert(size >= INET_ADDRSTRLEN);const struct sockaddr_in* addr4 = sockaddr_in_cast(addr);//网络字节序转换为点分十进制表示的 IPv4 或 IPv6 地址。写入buf::inet_ntop(AF_INET, &addr4->sin_addr, buf, static_cast<socklen_t>(size));}//判断ipv6else if (addr->sa_family == AF_INET6){assert(size >= INET6_ADDRSTRLEN);const struct sockaddr_in6* addr6 = sockaddr_in6_cast(addr);::inet_ntop(AF_INET6, &addr6->sin6_addr, buf, static_cast<socklen_t>(size));}
}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";}
}void sockets::fromIpPort(const char* ip, uint16_t port,struct sockaddr_in6* addr)
{addr->sin6_family = AF_INET6;addr->sin6_port = hostToNetwork16(port);if (::inet_pton(AF_INET6, ip, &addr->sin6_addr) <= 0){LOG_SYSERR << "sockets::fromIpPort";}
}int sockets::getSocketError(int sockfd)
{int optval;socklen_t optlen = static_cast<socklen_t>(sizeof optval);//获取当前套接口的错误状态。填入optlen参数if (::getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) < 0){return errno;}else{return optval;}
}struct sockaddr_in6 sockets::getLocalAddr(int sockfd)
{struct sockaddr_in6 localaddr;memZero(&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;
}struct sockaddr_in6 sockets::getPeerAddr(int sockfd)
{struct sockaddr_in6 peeraddr;memZero(&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;
}bool sockets::isSelfConnect(int sockfd)
{//获取本地地址struct sockaddr_in6 localaddr = getLocalAddr(sockfd);//获取远端地址struct sockaddr_in6 peeraddr = getPeerAddr(sockfd);//如果这是一个ipv4if (localaddr.sin6_family == AF_INET){const struct sockaddr_in* laddr4 = reinterpret_cast<struct sockaddr_in*>(&localaddr);const struct sockaddr_in* raddr4 = reinterpret_cast<struct sockaddr_in*>(&peeraddr);//判断本地和远端的ip和port是否相同return laddr4->sin_port == raddr4->sin_port&& laddr4->sin_addr.s_addr == raddr4->sin_addr.s_addr;}else if (localaddr.sin6_family == AF_INET6){return localaddr.sin6_port == peeraddr.sin6_port&& memcmp(&localaddr.sin6_addr, &peeraddr.sin6_addr, sizeof localaddr.sin6_addr) == 0;}else{return false;}
}

更多推荐

muduo源码剖析之SocketOps类

本文发布于:2023-11-16 06:49:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1614118.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源码   muduo   SocketOps

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!