Jack Huang's Blog


  • 首页

  • 标签

  • 归档

  • 搜索

从数据可视化角度理解大小端字节序问题

发表于 2024-05-11

大小端字节序问题让人十分头疼,死记硬背并不能加深对大小端字节序的理解。但是从数据可视化的角度,就能理解大小端字节序,让人豁然开朗。

问题来源

字节序,又称端序或尾序(英语中用单词:Endianness 表示),在计算机领域中,指电脑内存中或在数字通信链路中,占用多个字节的数据的字节排列顺序。

字节的排列方式有两个通用规则:

  • 大端序(Big-Endian)将数据的低位字节存放在内存的高位地址,高位字节存放在低位地址。这种排列方式与数据用字节表示时的书写顺序一致,符合人类的阅读习惯。
  • 小端序(Little-Endian),将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称小端序。小端序与人类的阅读习惯相反,但更符合计算机读取内存的方式,因为CPU读取内存中的数据时,是从低地址向高地址方向进行读取的。

通常在计算机内部,小端序被广泛应用于现代 CPU 内部存储数据;而在其他场景,比如网络传输和文件存储则使用大端序。

从网络数据可视化看大端序

一般网络字节序为大端字节序,因为UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,网络数据解析时先收到的数据存放于低地址,否则内存的访问将是不连续的。 所以,大端字节序 = 网络字节序 = 高位放低地址。

对于整形数0x11223344,采用网络传输时,从wireshark中抓到的消息包,如下所示:

1
2
3
4
5
        0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0000 11 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

从wireshark的数据可视化角度可知,网络通信采用大端序,低地址存储高位字节,高地址存储低位字节,符合人类阅读习惯。

从内存分布可视化看小端序

操作系统内存布局

Windows在默认情况下会将高地址的2GB空间分配给内核(也可以配置为1GB),而Linux默认情况下会将高地址的1GB空间分配给内核。也就是说,应用程序只能使用剩下的2GB或3GB的地址空间,称为用户空间(User Space)。

Windows 32位程序的内存分布

图1 Windows 32位程序的内存分布

应用程序性用户空间布局

  • 堆(heap)的增长方向是向上增长,即低地址向高地址增长。
  • 栈(stack)的增长方向是向下增长,即高地址向低地址增长。

Windows 32位程序的内存分布

图2 Windows 32位程序堆栈内存分配和增长方向

应用程序中定义的变量通常在栈区存储,而栈(stack)的增长方向是向下增长,即高地址向低地址增长。因此,从如下可视化角度查看数据是合理的。

1
2
3
4
5
        F  E  D  C  B  A  9  8  7  6  5  4  3  2  1  0
0030 11 22 33 44 00 00 00 00 00 00 00 00 00 00 00 00
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

参考链接

  1. 什么是大端序和小端序,为什么要有字节序?,by Kevin Yan.
  2. Windows下C语言程序的内存布局,by 朴素贝叶斯.
  3. 一文弄懂大小端字节序/网络字节序,by Linux加油站.
  4. 为什么堆和栈的增长方向相反?,by 嵌入式ARM.

CPlusPlus之让程序只启动一个实例

发表于 2024-05-07

C++中让程序只启动一个实例的方法主要有以下几种:

互斥体实现方式

主要利用如下函数实现:

1
2
3
4
5
6
函数原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,//必须为NULL
BOOL bInitialOwner, //表示mutex的范围是本线程还是全系统
LPCTSTR lpName //互斥量的名字
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool    checkMyselfExist()//如果程序已经有一个在运行,则返回true
{
HANDLE hMutex = CreateMutex(NULL, FALSE, L"DevState");
if (hMutex && (GetLastError() == ERROR_ALREADY_EXISTS))
{
CloseHandle(hMutex);
hMutex = NULL;
return true;
}
else{
return false;
}
}

int main()
{
if (checkMyselfExist()){
cout << "program has been runnin" << endl;
}
else{
cout << "start running" << endl;
}
system("pause");

return 0;
}

参考链接

  1. C++实现程序单实例运行的两种方式,by 倚剑问天.
  2. C / C++ 如何让程序只启动一个实例,by C你.

毛泽东选集全四卷读书笔记

发表于 2024-04-28

如果没有毛泽东同志多次从危机中挽救中国革命,如果没有以他为首的党中央给全党、全国各族人民和人民军队指明坚定正确的政治方向,我们党和人民可能还要在黑暗中摸索更长时间。同中国共产党被公认为全国各族人民的领导核心一样,毛泽东同志被公认为中国共产党和中国各族人民的伟大领袖,在党和人民集体奋斗中产生的毛泽东思想被公认为党的指导思想,这是中华人民共和国建国以前二十八年历史发展的必然结果。

金句摘抄

政治路线确定之后,干部就是决定的因素。【《毛泽东选集》第2卷,人民出版社1991年第2版,中国共产党在民族战争中的地位,第526页。】

参考链接

  1. 毛泽东选集[全四卷],by usst.
  2. 关于建国以来党的若干历史问题的决议,by 人民日报.

Tcpdump使用帮助

发表于 2024-04-24

tcpdump 用于收集有关网络流量数据的出色工具。 数据包捕获为故障排除和安全分析提供了有用的信息。

tcpdump 参数

参数 含义
-a 将网络地址和广播地址转变成名字
-c 在收到指定的包的数目后,tcpdump就会停止;
-d 将匹配信息包的代码以人们能够理解的汇编格式给出;以可阅读的格式输出。
-dd 将匹配信息包的代码以c语言程序段的格式给出;
-ddd 将匹配信息包的代码以十进制的形式给出;
-e 在输出行打印出数据链路层的头部信息;
-f 将外部的Internet地址以数字的形式打印出来;
-l 使标准输出变为缓冲行形式;
-n 直接显示IP地址,不显示名称;
-nn 端口名称显示为数字形式,不显示名称;
-t 在输出的每一行不打印时间戳;
-v 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
-vv 输出详细的报文信息;
-F 从指定的文件中读取表达式,忽略其它的表达式;
-i 指定监听的网络接口;
-r 从指定的文件中读取包(这些包一般通过-w选项产生);
-w 直接将包写入文件中,并不分析和打印出来;
-T 将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程调用)和snmp(简单 网络管理协议;)

使用举例

截获主机收到和发出的所有数据包

1
tcpdump

将抓包信息写入文件 -w

1
tcpdump -w tcpdump_test.pcap

导出的pcap文件可导入wireshark进行分析。

打印出所有可工作的接口 -D

1
tcpdump -D

指定监控的网卡 -i

1
tcpdump -i eth0

参考链接

  1. 肝了三天,整了一份全网最全(中文) tcpdump 抓包指南,by 游戏大爷君.
  2. 网络/命令行抓包工具tcpdump详解,by 一口Linux.

nodejs静态文件服务器Anywhere使用帮助

发表于 2024-04-20

Anywhere 是随启随用的静态文件服务器,它能随时随地将你的当前目录变成一个静态文件服务器的根目录。

安装

1
npm install anywhere -g

执行

切换到静态文件目录,输入以下命令测试:

1
2
3
4
5
6
7
8
9
10
11
$ anywhere
// or with port
$ anywhere -p 8000
// or start it but silent(don't open browser)
$ anywhere -s
// or with hostname
$ anywhere -h localhost -p 8888
// or with folder
$ anywhere -d ~/git/anywhere
// or enable html5 history
$ anywhere -f /index.html

参考链接

  1. anywhere,by npmjs
  2. nodejs服务器Anywhere使用,by 一包.

DTO模式学习

发表于 2024-04-11 | 更新于 2024-04-12

DTO模式首次被提出来是在 Martin Fowler 的 EAA 一书中,DTOs 或 Data Transfer Objects 是一种在进程中传递数据的对象,用来减少方法的调用。

根据 Martin Fowler 的解释,该模式的主要目的是通过在一次调用中批量处理多个命令参数,从而减少请求服务器的次数,进而减少远程操作的网络开销。

该模式的另一个好处是对序列化的逻辑(序列化是指将对象的结构和数据转换为特定模式用来存储或者传输的机制)进行了封装,提供了单一的变化点去修改序列化的逻辑。它还可以将领域模型与表现层解耦,允许两者独立变化而不互相影响。

参考链接

  1. The DTO Pattern (Data Transfer Object),by baeldung.
  2. [译] DTO模式,by iyichen.

Kylin系统下载完整deb包及依赖包

发表于 2024-04-11 | 更新于 2024-06-14

最近使用Kylin系统做开发,记录一下使用过程。

添加官方软件源

请参考:

  • 银河麒麟V4.0.2添加官方软件源

主要是修改source.list文件,添加如下内容:

1
deb http://archive.kylinos.cn/kylin/KYLIN-ALL 4.0.2-desktop main restricted universe multiverse

下载完整deb包及依赖包

查看virtualbox所依赖的deb包:

1
apt-cache depends virtualbox

下载virtualbox所依赖的deb包:

1
apt-get download $(apt-cache depends virtualbox | grep -v i386 | grep "依赖" | awk '{print substr($0,11)}')

安装所有deb包:

1
dpkg -i *.deb

搜索deb包

1
apt-cache search virtualbox

查看显卡信息

1
2
3
4
5
6
7
8
9
10
# 方法1
lspci | grep -i vga
lspci | grep -i nvidia
lspci -v -s 00:0f.0

# 方法2
lshw -C video
lshw -C display
lshw -C video | grep configuration
modinfo vboxvideo

参考链接

  1. ubuntu 下载完整deb包及依赖包,by lucky科技汪.
  2. 银河麒麟V4.0.2添加官方软件源,by 123无敌,就你了.
  3. grep,awk,cut 字符串截取,by WH·xiao.
  4. Linux中如何查看显卡硬件信息,by 系统极客.

Windows和Linux查看组播通信的方法

发表于 2024-03-25

最近研究一个网络程序,很复杂,用到了组播通信,就想知道其内部组播细节,记录一下相关命令。

Windows查看组播通信命令

1
2
ipconfig /all
netsh interface ipv4 show joins

Linux查看组播通信命令

1
2
3
netstat -g
ip maddr show
ip maddr show dev eth0

参考链接

  1. 在windows下查看加入的组播组,by ludepsea.
  2. linux查看组播信息,by juejin.
  3. 2022-02-03–银河麒麟-银河麒麟v4与.netcore安装,by Zen.Wu.

ACE网络库学习笔记

发表于 2024-03-20 | 更新于 2024-05-15

ACE自适配通信环境(ADAPTIVE Communication Environment)是可以自由使用、开放源码的面向对象(OO)框架(Framework),在其中实现了许多用于并发通信软件的核心模式。

ACE提供了一组丰富的可复用C++ Wrapper Facade(包装外观)和框架组件,可跨越多种平台完成通用的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。

ACE_Message_Queue

ACE消息队列,请参考:

  • 使用Message_Queue的经典的“有界缓冲区”的ACE实现

ACE_Message_Block

ACE_Message_Block用于构建“固定”和“可变”长度的消息。ACE_Message_Block可以将多条消息连接在一起,形成一个链表,从而支持复合消息。请参考:

  • ACE_Message_Block消息数据类
  • ACE_Message_Block—–ACE消息的存储

ACE_Thread_Manager

ACE线程管理类,请参考:

  • ACE_Thread_Manager(v3.12)

ACE日志设施

请参考:

  • 使用ACE日志设施(二)详细介绍(v4)

ACE组播通信

请参考:

  • ACE组播通信,by NoName.
  • linux网络编程之一—–多播(组播)编程 ,by 胡永光.

问题参考

ACE静态链接问题

请参考

  • ACE的”error LNK2019: unresolved external symbol”链接错误
  • ACE的开发和使用 - FAQ
  • How to solve unresolved external symbol error - if_nametoindex in visual studio 2013

ACE TCP Server无法Open的问题

最近突然发现ACE_SOCK_Acceptor.open方法报错,无法初始化,错误代码是10093,通过分析是WSAStartup()未初始化。最后在main函数文件中通过 #include <ace/OS_main.h> 解决。解决原因是该文件中将调用 WSAStartup() 函数初始化。

1
2
3
4
5
ACE_INET_Addr commAddr(1500);
if (m_acceptor->open(commAddr, 1) == -1) {
ACE_DEBUG((LM_ERROR, "errno=%d", ACE_OS::last_error()));
return -1;
}

ACE 多网口多播问题

当多播时存在多个网口,应指定多播绑定的网口。参考如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "ace/SOCK_Dgram_Mcast.h"
#include "ace/Log_Msg.h"

int main()
{
ACE_SOCK_Dgram_Mcast mcast;
ACE_INET_Addr srv_addr("224.0.0.9:520");

/*
if (mcast.open(srv_addr, "eth0", 1) == -1)
{
ACE_ERROR_RETURN((LM_ERROR, "%p"), -1);
}*/

mcast.join(srv_addr,1,"eth0");
}

参考链接

  1. ACE 示例2 — Echo Server,by peirenlei.
  2. ACE自适配通信环境,by wikipedia.
  3. 服务器并发策略,by maodanp.
  4. Threads and Connections in Backend Applications,by Hussein Nasser.
  5. error LNK2019: 无法解析的外部符号 “int __cdecl ace_main_i(int,char * * const)” ,by 金士顿.
  6. Windows Sockets Error Codes,by microsoft.
  7. WSAStartup 函数 (winsock.h),by microsoft.
  8. socket 函数 (winsock2.h),by microsoft.
  9. ACE_SOCK,by 咚咚锵锵.
  10. C++ Winsock 10093 error,by stackoverflow.
  11. ACE_SOCK_Dgram_Mcast Class Reference,by vanderbilt.

SpringBoot学习笔记

发表于 2024-03-16 | 更新于 2025-04-21

Spring Boot 是一个基于 Java 的开源框架,用于以最小的工作量编写独立的、生产级的基于 Spring 的应用程序。Spring Boot 是 Spring Java 平台的约定优先于配置的扩展,旨在帮助在创建基于 Spring 的应用程序时最大程度地减少配置问题。

由于其易用性和健壮性,它被广泛用于构建微服务、Web 应用程序和其他基于 Java 的项目。

常用工具介绍

mvn repository

访问地址如下,用于查找Jar包

  • mvnrepository

当前很多项目使用mvn打包多模块,请参考:

  • Maven打包方式(多模块)

MyBatis

MyBatis-Plus

请参考:

  • MyBatis org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题解决

代码生成器新,请参考:

  • Mybatis Plus最新代码生成器AutoGenerator,更简单更高效!

SWagger

Swagger是一个可以根据你的代码,自动生成接口文档的一个工具,并且可以用作接口测试工具。

请参考:

  • springboot3.x集成SpringDoc Swagger3
  • 从 SpringFox 迁移到 SpringDoc

分层架构

参考SprintBoot的分层架构,可以更好的开发企业级应用。请参考:

  • Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
  • 在Spring Boot开发中使用DTO层
  • 真理大讨论:Service层的接口是不是多此一举?
  • Spring Boot中的业务层(Service)是否要创建接口,以及如果Service有多个实现类,如何让Spring知道该注入哪个Impl类的分析
  • 深入理解Spring Boot的Service层
  • 五个分层维度:Spring Boot 工程分层实战
  • 分层设计:Service 层真的需要实现接口吗?
  • 基于Spring框架的分层解耦详解

跨域问题

在用SpringBoot开发后端服务时,我们一般是提供接口给前端使用,但前端通过浏览器调我们接口时,浏览器会有个同源策略的限制,即协议,域名,端口任一不一样时都会导致跨域,这篇文章主要介绍跨域的几种常用解决方案。

具体方案请参考:

  • SpringBoot 项目解决跨域的几种方案

测试跨域问题

注意,当前以下代码无法在最新的Chrome浏览器控制台运行:

1
2
3
4
5
6
7
8
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:9090/user') // 替换请求的方法和地址
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText)
}
}

可使用Postman进行跨域测试,请参考:

  • Postman 中如何进行跨域(CORS)测试?图文教程

具体原理是:跨域问题源于浏览器同源策略,Postman 提供了模拟 CORS 请求的便捷方法,通过设置 Origin 字段和测试跨域请求,可检查响应头中的Access-Control-Allow-Origin等信息。

maven父子工程中的依赖引用

请参考:

  • 一文搞懂maven父子工程中的依赖引用

注解

@AliasFor注解

请参考:

  • SpringBoot深入理解 – @AliasFor注解的作用
  • @AliasFor 注解
  • Spring Boot常用注解(一) - 声明Bean的注解

@Component注解

请参考:

  • SpringBoot - @Component注解使用详解

@Service注解

请参考:

  • Spring5:@Autowired注解、@Resource注解和@Service注解
  • Spring注解之Service详解

@Configuration注解

请参考:

  • Spring Boot 中的 @Configuration 注解

@Aspect 注解

请参考:

  • Spring Boot中的 @Aspect 注解是什么,如何使用
  • @Aspect结合案例详解(一)
  • 基于@Aspect注解实现的SpringBoot AOP源码
  • Spring Boot 自定义注解实现AOP切面织入
  • Spring Boot 使用自定义注解实现操作日志的记录
  • AOP面向切面编程@Aspect 注解用法
  • 关于切点表达式中 @annotation 用法的疑问
  • SpringBoot AOP中JoinPoint的用法和通知切点表达式
  • SpringBoot Aop 详解和多种使用场景

@RestControllerAdvice注解

请参考:

  • RestControllerAdvice注解与全局异常处理

Actuator

在Spring Boot应用中,只需要依赖组件spring-boot-starter-actuator。它提供了很多监控和管理你的Spring Boot应用的HTTP或者JMX端点,并且你可以有选择地开启和关闭部分功能。当你的Spring Boot应用中引入依赖之后,将自动拥有审计、健康检查、Metrics监控等功能。

请参考:

  • SpringBoot中集成Actuator实现监控系统运行状态

实体类划分

在项目应用中,VO对应于页面上需要显示的数据(表单),DO对应于数据库中存储的数据(数据表),DTO对应于除二者之外需要进行传递的数据。

  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

  • DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。

  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

  • PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

请参考:

  • 实体类(VO,DO,DTO)的划分

Spring Security

请参考:

  • 秒懂SpringBoot之全网最易懂的Spring Security教程

PageHelper分页插件

请参考:

  • mybatis分页插件PageHelper使用及原理分析
  • Springboot Mybatis使用pageHelper实现分页查询

代码自动生成

请参考:

  • 使用 Velocity 模板引擎快速生成代码

定时任务

请参考:

  • 深入Quartz,更优雅地管理你的定时任务

部署方式

请参考:

  • 花5分钟过一遍jar包和war包的区别

参考链接

  1. Spring Boot,by spring.
  2. 从0开始带你手撸一套SpringBoot+Vue后台管理系统,让小白能跟着学会的项目实战,by 程序员青戈.
  3. SpringBoot 项目解决跨域的几种方案,by JK凯.
  4. springboot3.x集成SpringDoc Swagger3,by 咚咚阳.
  5. mvnrepository,by mvn.
  6. Spring中 Service和ServiceImpl的选择,by leeindex.
  7. Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程,by Leaton Lee.
上一页1…567…53下一页

Jack Huang

523 日志
67 标签
© 2025 Jack Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse