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…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...