【Muduo】套接字:InetAddress、Socket

2024-05-24 01:52

本文主要是介绍【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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/997039

相关文章

Java Socket服务器端与客户端的编程步骤总结

一,InetAddress类: InetAddress类没有构造方法,所以不能直接new出一个对象; 可以通过InetAddress类的静态方法获得InetAddress的对象; InetAddress.getLocalHost(); InetAddress.getByName(""); 类主要方法: String - address.getHostName(); String - addre

VC环境下window网络程序:UDP Socket程序

最近在学Windows网络编程,正好在做UDPsocket的程序,贴上来: 服务器框架函数:              socket();    bind();    recfrom();  sendto();  closesocket(); 客户机框架函数:            socket();      recfrom();  sendto();  closesocket();

socket()接口与内核协议栈的挂接

最近在看Brdige的代码,发现一个问题,同样的调用ioctl接口实现添加网桥、删除网桥、网桥增加网卡、网桥删除网卡等操作,一个应用层的接口,却通过两条路径实现,sock_ioctl和RTNETLINK(这本就不是一个级别的东西),而应用层的brctl-utils源码中并没有直接使用PF_NETLINK协议簇的情况,让我感到非常奇怪,因此想把glibc到系统调用,到协议簇注册,以及和VFS的关系再

linux下的Socket网络编程教程

套接字概念 Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。与管道类似的,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传递。在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。

微软C#套接字异步通信代码

Asynchronous Server Socket Example.NET Framework 4 其他版本 The following example program creates a server that receives connection requests from clients. The server is built with an asynchronous socket,

socket函数接收发送详解

http://blog.csdn.net/g_brightboy/article/details/12854117 http://blog.csdn.net/liangkaiyang/article/details/5931901 send。。。 这里只描述同步Socket的send函数的执行流程。 当调用该函数时,send先比较待发送数据的长度

linux下socket常用函数

1、setprotoent(打开网络协议的数据文件) 相关函数  getprotobyname, getprotobynumber, endprotoent 表头文件  #include <netdb.h> 定义函数  void setprotoent (int stayopen); 函数说明      setprotoent()用来打开/etc/protocols,如果参数

套接字的介绍

套接字(Socket)是计算机网络中用于实现不同主机之间通信的一种抽象概念。它提供了一种标准的接口,使得应用程序能够通过网络发送和接收数据。以下是关于套接字的详细介绍: 1. 套接字的基本概念 定义:套接字是一种用于网络通信的端点,通常由 IP 地址和端口号组成。它允许不同的程序进行网络通信。类型: 流套接字(TCP Socket):使用传输控制协议(TCP),提供可靠的、面向连接的通信。数据

JAVAEE初阶第六节——网络编程套接字

系列文章目录 JAVAEE初阶第六节——网络编程套接字 文章目录 系列文章目录JAVAEE初阶第六节——网络编程套接字 一. 网络编程基础1. 为什么需要网络编程2. 什么是网络编程3.网络编程中的基本概念 3.1 发送端和接收端 3.2 请求和响应 3.3 客户端和服务端 4. 常见的客户端服务端模型 5. TCP和UDP特点上的差别(初识) 二.Socket套接字 1. 概

udp网络通信 socket

套接字是实现进程间通信的编程。IP可以标定主机在全网的唯一性,端口可以标定进程在主机的唯一性,那么socket通过IP+端口号就可以让两个在全网唯一标定的进程进行通信。 套接字有三种: 域间套接字:实现主机内部的进程通信的编程 原始套接字:使用网络层或者数据链路层的接口进行编程,更难更底层,例如制作抓包等网络工具 网络套接字:实现用户通信的编程 udp网络通信 服务端server 分