muduo网络库剖析——网络地址InetAddress类
muduo网络库剖析——网络地址InetAddress类
- 前情
- 从muduo到my_muduo
- 概要
- socketaddr_in
- 介绍
- 成员用法
- 网络地址转换函数
- 框架与细节
- 成员
- 函数
- 使用方法
- 源码
- 结尾
前情
从muduo到my_muduo
作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足;而作为学习者,我们需要抽取其中的精华进行简要实现,这要求我们足够了解muduo库。
做项目 = 模仿 + 修改,不要担心自己学了也不会写怎么办,重要的是积累,学到了这些方法,如果下次在遇到通用需求的时候你能够回想起之前的解决方法就够了。送上一段话!

概要
socketaddr_in
介绍
sockaddr是一个用于存储套接字地址的结构体,它可以表示不同类型的地址,包括IPv4、IPv6等。它通常用于bind、connect、recvfrom和sendto等函数的参数,指明地址信息。然而,sockaddr结构体存在一些弊端,其中最主要的是sa_data字段将目标地址和端口信息混在一起,这导致在使用某些网络函数时需要额外的处理才能正确地获取地址和端口信息。
为了解决sockaddr的缺陷,出现了sockaddr_in结构体。与sockaddr相比,sockaddr_in结构体将port和addr分开储存在两个变量中,分别对应sin_port和sin_addr字段。这种结构使得地址和端口信息更加清晰,易于处理。同时,sockaddr_in结构体还提供了方便的函数来操作地址和端口信息,例如inet_pton和inet_ntop等。
总的来说,sockaddr_in相对于sockaddr具有更加清晰的结构和易于操作的字段,因此在网络编程中通常更受欢迎。虽然sockaddr仍然可以使用,但在处理IPv4地址时建议使用sockaddr_in结构体。

成员用法
sin_family
sin_family是sockaddr_in结构体中的一个字段,用于指定地址家族。在IPv4中,sin_family的值为AF_INET,表示使用IPv4地址。在IPv6中,sin_family的值为AF_INET6,表示使用IPv6地址。因此,sin_family字段用于指明地址类型,以便正确地处理和传输网络通信数据。sin_addr
sin_addr是一个用于存储IP地址的字段,它是sockaddr_in结构体的一部分。sin_addr字段通常用于表示IPv4地址,使用无符号长整型(unsigned long)类型来存储32位的IP地址。通过使用inet_addr函数可以将字符串形式的IP地址转换为unsigned long类型的IP地址,并将其赋值给sin_addr字段。在处理网络通信时,sin_addr字段用于指明目标主机或服务器的IP地址,以便正确地建立连接和传输数据。需要注意的是,sin_addr字段的值应该以网络字节序存储,因为网络通信中通常使用网络字节序进行数据传输。sin_port
sin_port是一个用于存储端口号的字段,它是sockaddr_in结构体的一部分。sin_port字段的数据类型是16位的无符号整数,用于表示端口号。端口号的取值范围通常为065535,其中01023为系统保留的端口号,一般由系统分配给特定的服务程序。用户可以使用1024~65535之间的端口号。在处理网络通信时,sin_port字段用于指明目标主机或服务器的端口号,以便正确地建立连接和传输数据。需要注意的是,sin_port字段的值应该以网络字节序存储,因为网络通信中通常使用网络字节序进行数据传输。如果需要在主机字节序和网络字节序之间进行转换,可以使用htons函数将主机字节序转换为网络字节序,使用ntohs函数将网络字节序转换为主机字节序。sin_zero
sin_zero是一个通常不使用的字段,它是sockaddr_in结构体的一部分。sin_zero字段的存在只是为了与通用套接字地址结构struct sockaddr在内存中对齐,通常会被置为0。因此,在实际的网络编程中,很少使用sin_zero字段。
网络地址转换函数
-
int inet_aton(const char *cp, struct in_addr *inp);
inet_aton()将Internet主机地址cp从IPv4数字和点符号转换为二进制形式(以网络字节顺序),并将其存储在inp指向的结构中。Inet_aton()如果地址有效则返回非零,如果无效则返回零。
如果提供的字符串被成功解释,Inet_aton()返回1,如果字符串无效(错误时没有设置errno)则返回0。

-
in_addr_t inet_addr(const char *cp);
inet_addr()函数的作用是:将Internet主机地址cp从IPv4的数字点法转换为网络字节顺序的二进制数据。如果输入无效,则返回INADDR_NONE(通常为-1)。使用这个函数是有问题的,因为-1是一个有效的地址(255.255.255.255)。避免使用它,而应使用inet_aton()、inet_pton(3)或getaddrinfo(3),它们提供了一种更清晰的方式来指示错误返回。 -
in_addr_t inet_network(const char *cp);
inet_network()函数的作用是将cp (IPv4数字和点表法中的字符串)转换为适合用作Internet网络地址的主机字节顺序的数字。如果成功,则返回转换后的地址。如果输入无效,则返回-1。 -
char *inet_ntoa(struct in_addr in);
inet_ntoa()函数的作用是:将Internet主机地址(以网络字节顺序给出)转换为IPv4点分十进制格式的字符串。字符串在静态分配的缓冲区中返回,后续调用将覆盖该缓冲区。 -
inet_pton(int af, const char *src, void *dst)
该函数将字符串src转换为af地址族中的网络地址结构,然后将该网络地址结构复制到dst。参数af必须是AF_INET或AF_INET6。DST是按网络字节顺序写的。
Inet_pton()成功时返回1(网络地址已成功转换)。0如果SRC不包含表示指定地址族中有效网络地址的字符串,则返回。如果af不包含有效的地址族,则返回-1并将errno设置为EAFNOSUPPORT。
与inet_aton(3)和inet_addr(3)不同,inet_pton()支持IPv6地址。另一方面,inet pton()只接受点分十进制表示法的IPv4地址,而inet_aton(3)和inet_addr(3)允许更通用的数字和点表示法(十六进制和八进制数字格式,以及不需要显式写入所有四个字节的格式)。对于同时处理IPv6 ad- 1地址和数字点表示法的IPv4地址的接口,请参见getaddrinfo(3). -
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
这个函数将af地址族中的网络地址结构src转换为字符串。结果字符串被复制到dst所指向的缓冲区,dst必须是一个非空指针。调用方在参数size中指定此缓冲区中可用的字节数。
Inet_ntop()扩展了inet_ntoa(3)函数以支持多个地址族,inet_ntoa(3)现在被认为是不推荐的,而支持Inet_ntop()。目前支持的地址族如下:

如果成功,inet_ntop()返回一个指向dst的非空指针。如果有错误,则返回NULL,并设置errno来指示错误。 -
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

框架与细节
成员

成员是一个sockaddr_in结构体,具体见上面介绍。
函数

主要是构造函数,构造分为sockaddr_in构造和ip地址,端口号构造。网络地址结构的设置与获取,以及网络地址的打印。

其中主要用到的函数,inet_pton与inet_ntop,将字符串src转换为af地址族中的网络地址结构与将af地址族中的网络地址结构src转换为字符串。htons与ntohs,主机端口号变成网络端口号与网络端口号变成主机端口号。
使用方法

源码
//InetAddress.h
#pragma once#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>#include "copyable.h"
#include "Log.h"class InetAddress : copyable {
public:InetAddress(uint16_t port = 8000, const char* ip = "127.0.0.1");InetAddress(sockaddr_in addr) {addr_ = addr;}uint16_t toPort() const {return ntohs(addr_.sin_port);}std::string toIp() const;std::string toIpPort() const;sa_family_t family() const {return addr_.sin_family;}sockaddr_in* getSockAddr() { return &addr_; }void setSockAddr(sockaddr_in addr) { addr_ = addr; }void setSockAddr(uint16_t port, const char* ip);
private:struct sockaddr_in addr_;
};//InetAddress.cpp
#include "InetAddress.h"std::string InetAddress::toIpPort() const {return toIp() + " : " + std::to_string(toPort());
}std::string InetAddress::toIp() const {char buf[64] = {0};if (::inet_ntop(addr_.sin_family, &addr_.sin_addr, buf, sizeof buf) == nullptr) {LOG_ERROR("%s--%s--%d--%d : inet_ntop error\n", __FILE__, __FUNCTION__, __LINE__, errno);}return buf;
}InetAddress::InetAddress(uint16_t port, const char* ip) {bzero(&addr_, sizeof addr_);addr_.sin_family = AF_INET;if (::inet_pton(addr_.sin_family, ip, &addr_.sin_addr) != 1) {LOG_FATAL("%s--%s--%d--%d : inet_pton error\n", __FILE__, __FUNCTION__, __LINE__, errno);}addr_.sin_port = htons(port);
}void InetAddress::setSockAddr(uint16_t port, const char* ip) {bzero(&addr_, sizeof addr_);addr_.sin_family = AF_INET;if (::inet_pton(addr_.sin_family, ip, &addr_.sin_addr) != 1) {LOG_FATAL("%s--%s--%d--%d : inet_pton error\n", __FILE__, __FUNCTION__, __LINE__, errno);}addr_.sin_port = htons(port);
}
结尾
以上就是网络地址InetAddress类的相关介绍,以及我在进行项目重写的时候遇到的一些问题,和我自己的一些心得体会。发现写博客真的会记录好多你的成长,而且对于一个好的项目,写博客也是证明你确实有过深度思考,并且在之后面试或者工作时遇到同样的问题能够进行复盘的一种有效的手段。所以,希望uu们也可以像我一样,养成写博客的习惯,逐渐脱离菜鸡队列,向大佬前进!!!加油!!!
也希望我能够完成muduo网络库项目的深度学习与重写,并在功能上能够拓展。也希望在完成这个博客系列之后,能够引导想要学习muduo网络库源码的人,更好地探索这篇美丽繁华的土壤。致敬chenshuo大神!!!
鉴于博主只是一名平平无奇的大三学生,没什么项目经验,所以可能很多东西有所疏漏,如果有大神发现了,还劳烦您在评论区留言,我会努力尝试解决问题!
相关文章:
muduo网络库剖析——网络地址InetAddress类
muduo网络库剖析——网络地址InetAddress类 前情从muduo到my_muduo 概要socketaddr_in介绍成员用法 网络地址转换函数 框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足&…...
什么是本地IP?服务器本地IP有哪些优势?
本地IP是指直接在互联网上分配给服务器或设备的IP地址,而不是通过NAT(网络地址转换)或 代理等中间设备进行转发。让我们关注本地IP的优势。 1.直接访问:原始IP允许无中间设备转发或代理直接访问服务器或设备。这减少了网络延迟&a…...
Open CASCADE学习|参数化球面的奇异性
参数曲面的奇异性是一个相对复杂的概念,它涉及到参数曲面的几何特性和参数化过程中的一些特殊情况。参数曲面通常用于描述三维空间中的复杂形状,通过参数方程将二维参数域映射到三维空间中。然而,在某些情况下,参数曲面可能会表现…...
基础知识篇(一)Acticity生命周期
Activity 类是 Android 应用的关键组件,而 activity 的启动和组合方式是平台应用模型的基本组成部分。与使用 main() 方法启动应用的编程范式不同,Android 系统会通过调用与其生命周期特定阶段对应的特定回调方法,在 Activity 实例中启动代码…...
Java内存结构
前文: 《Java8之类的加载》 《Java8之类加载机制class源码分析》 写在开头:本文为学习后的总结,可能有不到位的地方,错误的地方,欢迎各位指正。 JVM 在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数…...
Java--ListUtil工具类,实现将一个大列表,拆分成指定长度的子列表
文章目录 前言实现代码执行结果 前言 在项目中有时会出现列表很大,无法一次性批量操作,我们需要将列表分成指定大小的几个子列表,一份一份进行操作,本文提供这样的工具类实现这个需求。 实现代码 以下为ListUtil工具类代码实现…...
SpringSecurity 密码加密登录
SpringSecurity 密码加密登录 1.前端所需文件2.后端所用工具类3.登录代码4.灵魂一问 1.前端所需文件 import JSEncrypt from jsencrypt/bin/jsencrypt.min// 密钥对生成 http://web.chacuo.net/netrsakeypairconst publicKey MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqz…...
大模型实战作业03
大模型实战作业03 注: 因为微调数据较少,没有显示出个人助手的名字...
【AI视野·今日Sound 声学论文速览 第四十四期】Tue, 9 Jan 2024
AI视野今日CS.Sound 声学论文速览 Tue, 9 Jan 2024 Totally 27 papers 👉上期速览✈更多精彩请移步主页 Daily Sound Papers DJCM: A Deep Joint Cascade Model for Singing Voice Separation and Vocal Pitch Estimation Authors Haojie Wei, Xueke Cao, Wenbo Xu…...
Windows Copilot 更新及使用教程
Windows Copilot 是一款由微软开发的人工智能辅助工具,可以通过学习用户的操作习惯和上下文,自动完成代码编写和其他重复性任务。它可以帮助开发人员提高工作效率,减少重复劳动。 以下是关于Windows Copilot的更新和使用教程的一些信息&…...
【Android开发】不同Activity之间的数据回传实例(一)摘桃子游戏
一、功能介绍 该项目实现的功能主要有: 在首页显示一个按钮点击该按钮跳转到桃园页面在桃园页面,点击桃子会弹窗显示摘到几个桃子,同时被点击桃子消失,总桃子数1点击退出桃园会返回首页,首页桃子数会根据点击的桃子数…...
增量式PID和脉冲轴组合控制阀门开度(算法介绍)
这篇博客我们以S7-1200PLC平台来举例,介绍我们的PID闭环控制器如何控制脉冲轴实现阀门角度控制。SMART PLC PID控制器控制伺服驱动器实现关节角度控制详细内容请参考下面文章: https://rxxw-control.blog.csdn.net/article/details/129658364https://rxxw-control.blog.csdn…...
解决Vue.js Devtools未检测到Vue实例的问题
解决Vue.js Devtools未检测到Vue实例的问题 解决Vue.js Devtools未检测到Vue实例的问题1. 确保Vue.js已正确加载1.1 在HTML文件中直接引入1.2 在构建工具(如Webpack)中配置引入1.3 检查与验证 2. 检查Vue.js Devtools扩展安装状态2.1 打开Chrome浏览器扩…...
【Java基础】进程与线程,并发与并行,CPU单核与多核
目录 1 进程与线程2 CPU单核与多核 1 进程与线程 进程与线程基本单位的对象不同 进程是操作系统进行资源分配(包括cpu、内存、磁盘IO等)的最小单位线程是CPU调度和分配的基本单位 CPU看不到进程,只能看到待分配的一些线程 并发与并行 并发&…...
git修改最新提交(commit)信息
一、修改最近一次commit信息 1、首先通过git log查看commit信息 2、使用命令git commit --amend进入命令命令模式,按i进入编辑模式,修改好commit信息后按Esc键退出编辑模式,然后输入:wq保存编辑信息(注意使用英文输入法…...
想寻找Axure的替代品?我们已经试用了10+款设计工具,来看看吧!
Axure是许多产品经理和设计师进入快速原型设计的首选工具,但Axure的使用成本相对较高,学习曲线陡峭,许多设计师正在寻找可以取代Axure的原型设计工具,虽然现在有很多可选的设计工具,但质量不均匀,可以取代A…...
报文大小限制、请求体类型总结
文章目录 1. 各节点请求体有无限制1.1 http协议1.2 TCP/IP层限制1.3 浏览器1.4 nginx1.5 gateway1.6 tomcat1.7 springboot1.8 内存、磁盘处理不了一切白搭 2. 请求体类型2.1 application/x-www-form-urlencoded2.2 multipart/form-data2.3 application/json2.4 text/plain2.5 …...
rknn加载onnx时报错 GLIBC=2.29 no found librknnc.so
rknn 中onnx转rknn在虚拟机中运行时发现报错. GLIBC2.29 no found /****/librknnc.so 昨天还正常的, 今天装了个ftp 和宝塔面板就出错了. 我估计根据报错地址, 找到了librknnc.so文件, 权限也给了777仍然不行 , 我怀疑是GLIBC的版本不对 ,网上给的方法是下载源码, 然后自己手动…...
ASP .net core微服务实战(杨中科)
背景: 主要是思考下,我们为什么要用微服务? 微服务我现在理解是:提供了我们一种模块化的手段,一个服务负责一种类型的业务,是一种面对复杂问题进行拆分的方式,但是也会引入一些中间件…...
使用命令行方式搭建uni-app + Vue3 + Typescript + Pinia + Vite + Tailwind CSS + uv-ui开发脚手架
使用命令行方式搭建uni-app Vue3 Typescript Pinia Vite Tailwind CSS uv-ui开发脚手架 项目代码以上传至码云,项目地址:https://gitee.com/breezefaith/uniapp-vue3-ts-scaffold 文章目录 使用命令行方式搭建uni-app Vue3 Typescript Pinia V…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
