本文主要是介绍【Muduo】套接字:InetAddress、Socket,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在 Muduo中,InetAddress和Socket是偏向底层的两个模块,封装了底层的一些系统调用,提供了好用的接口。
InetAddress
InetAddress通常用于表示一个网络地址。在 Muduo中,它可能是一个类,用于封装 IP 地址和端口号。
- IP 地址和端口号:使用 sockaddr_in 存储和表示一个 IP 地址(可以是 IPv4 或 IPv6)和一个端口号。
- 解析地址:可以从字符串形式的 IP 地址和端口号(如 "127.0.0.1:80")解析出 InetAddress对象。
- 转换为字符串:可以将 InetAddress对象转换回其字符串表示形式。
- 获取 IP 地址和端口号:可以获取 InetAddress对象中的 IP 地址和端口号。
Socket
Socket是网络编程中的一个基本概念,它代表了一个端点,用于在网络上进行通信。在 Muduo中,Socket是一个类,用于封装底层的 socket 句柄(或文件描述符)和相关的网络操作。
- 创建和销毁:创建和销毁一个 socket,包括设置 socket 的类型(如 TCP 或 UDP)、地址族(如 IPv4 或 IPv6)等。
- 绑定和监听:对于服务器端的 socket,可以通过 bindAddress 将其绑定到一个特定的地址和端口,并通过 listen 开始监听连接请求;对于已连接的客户端socket,可以设置其选项。
- 连接:对于客户端的 socket,可以 accept 连接到服务器端的 socket。
- 设置选项:可以设置 socket 的各种选项,如超时时间、缓冲区大小等。
- 关闭:关闭 socket,释放相关资源。
源码
InetAddress.h
#pragma once
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string>
#include <string.h>// 封装socket地址类型
class InetAddress
{
public:explicit InetAddress(uint16_t port = 0, std::string ip = "127.0.0.1");explicit InetAddress(const sockaddr_in &addr): addr_(addr){}std::string toIp() const;std::string toIpPort() const;uint16_t toPort() const;const sockaddr_in *getSockAddr() const { return &addr_; }void setSockAddrInet(const sockaddr_in &addr) { addr_ = addr; };private:sockaddr_in addr_;
};
InetAddress.cc
#include "InetAddress.h"InetAddress::InetAddress(uint16_t port, std::string ip)
{memset(&addr_, 0, sizeof(addr_));addr_.sin_family = AF_INET;addr_.sin_addr.s_addr = inet_addr(ip.c_str()); // 1、将ip地址转为点分十进制的整数表示 2、转为网络字节序addr_.sin_port = htons(port); // 本地字节序转为网络字节序
}std::string InetAddress::toIp() const
{char buf[64] = {0};//inet_ntop函数用于将网络地址(如IPv4或IPv6地址)从其网络字节序的内部表示形式转换为人类可读的字符串形式::inet_ntop(AF_INET, &addr_.sin_addr, buf, sizeof buf);return buf;
}std::string InetAddress::toIpPort() const
{// ip:portchar buf[64] = {0};::inet_ntop(AF_INET, &addr_.sin_addr, buf, sizeof buf);size_t end = strlen(buf);uint16_t port = ntohs(addr_.sin_port);sprintf(buf+end, ":%u", port);return buf;
}uint16_t InetAddress::toPort() const
{uint16_t port = ntohs(addr_.sin_port);return port;
}
Socket.h
#pragma once#include "noncopyable.h"class InetAddress;class Socket
{
public:Socket(int sockfd): sockfd_(sockfd){}~Socket();int fd() const { return sockfd_; }/// abort if address in usevoid bindAddress(const InetAddress &localaddr);/// abort if address in usevoid 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.int accept(InetAddress *peeraddr);void shutdownWrite();/// Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).void setTcpNoDelay(bool on);/// Enable/disable SO_REUSEADDRvoid setReuseAddr(bool on);/// Enable/disable SO_REUSEPORTvoid setReusePort(bool on);/// Enable/disable SO_KEEPALIVEvoid setKeepAlive(bool on);private:const int sockfd_;
};
Socket.cc
#include "Socket.h"
#include "InetAddress.h"
#include "LogStream.h"#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "netinet/tcp.h"Socket::~Socket()
{::close(sockfd_);
}void Socket::bindAddress(const InetAddress &localaddr)
{if (0 != ::bind(sockfd_, (sockaddr *)localaddr.getSockAddr(), sizeof(sockaddr_in))){LOG_FATAL << "Socket::bindAddress error, errno: " << errno;}
}void Socket::listen()
{LOG_DEBUG << "Socket::listen()";// 定义了一个 “等待连接队列” 的最大长度为1024// 队列用于存储那些已经到达服务器但尚未被 accept() 系统调用处理的连接请求if (0 != ::listen(sockfd_, 1024)){LOG_FATAL << "Socket::listen error, errno: " << errno;}
}int Socket::accept(InetAddress *peeraddr)
{/*** 1. accept函数的参数不合法* 2. 对返回的connfd没有设置非阻塞* Reactor模型:one loop per thread* poller + non-blocking IO*/LOG_DEBUG << "Socket::accept(InetAddress *peeraddr) : " << peeraddr->toIpPort();sockaddr_in addr;socklen_t len = sizeof addr;memset(&addr, 0, sizeof addr);int connfd = ::accept4(sockfd_, (sockaddr *)&addr, &len, SOCK_NONBLOCK | SOCK_CLOEXEC);if (connfd >= 0){peeraddr->setSockAddrInet(addr);}return connfd;
}void Socket::shutdownWrite()
{if (::shutdown(sockfd_, SHUT_WR) < 0){LOG_ERROR << "Socket::shutdownWrite() error, errno: " << errno;}
}void Socket::setTcpNoDelay(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, IPPROTO_TCP, TCP_NODELAY,&optval, static_cast<socklen_t>(sizeof optval));
}void Socket::setReuseAddr(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR,&optval, static_cast<socklen_t>(sizeof optval));
}void Socket::setReusePort(bool on)
{int optval = on ? 1 : 0;int ret = ::setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT,&optval, static_cast<socklen_t>(sizeof optval));if (ret < 0 && on){LOG_ERROR << "SO_REUSEPORT failed.";}
}void Socket::setKeepAlive(bool on)
{int optval = on ? 1 : 0;::setsockopt(sockfd_, SOL_SOCKET, SO_KEEPALIVE,&optval, static_cast<socklen_t>(sizeof optval));
}
这篇关于【Muduo】套接字:InetAddress、Socket的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!