Linux 网络编程学习笔记——五、Linux 网络编程基础 API
创始人
2025-06-01 12:22:49
0

一、socket 地址 API

1. 主机字节序和网络字节序

现代 CPU 的累加器一次都能装载(至少)4 字节(下面均考虑 32 位机),即一个整数。那么这 4 字节在内存中排列的顺序将影响它被累加器装载成的整数的值。这就是字节序问题。字节序分为大端字节序(big endian)和小端字节序(little endian)。

  • 大端字节序:指一个整数的高位字节(23 ~ 31 bit)存储在内存的低地址处,低位字节(0 ~ 7 bit)存储在内存的高地址处;
  • 小端字节序:指整数的高位字节存储在内存的高地址处,而低位字节则存储在内存的低地址处。

现在 PC 大多采用小端字节序,因此小端字节序又被称为主机字节序。当格式化的数据(比如 32 bit 整型数和 16 bit 短整型数)在两台使用不同字节序的主机之间直接传递时,接收端必然错误地解释之。解决问题的方法是:发送端总是把要发送的数据转化成大端字节序数据后再发送,而接收端知道对方传送过来的数据总是采用大端字节序,所以接收端可以根据自身采用的字节序决定是否对接收到的数据进行转换(小端机转换,大端机不转换)。因此大端字节序也称为网络字节序,它给所有接收数据的主机提供了一个正确解释收到的格式化数据的保证。

需要指出的是,即使是同一台机器上的两个进程(比如一个由 C 语言编写,另一个由 JAVA 编写)通信,也要考虑字节序的问题(JAVA虚拟机采用大端字节序)。

Linux 提供了 4 个函数来完成主机字节序和网络字节序之间的转换:

#include<netinet/in.h>
unsigned long int htonl(unsigned long int hostlong);  // host long to network long
unsigned short int htons(unsigned short int hostshort);  // host short to network short
unsigned long int ntohl(unsigned long int netlong);  // network long to host long
unsigned short int ntohs(unsigned short int netshort);  // network short to host short

2. 通用 socket 地址

socket 网络编程接口中表示 socket 地址是结构体 sockaddr :

#include<bits/socket.h>
struct sockaddr {sa_family_t sa_family;  // 地址族类型 地址族类型变量char sa_data[14];
}

地址族类型通常与协议族类型对应,常见的协议族(protocol family,domain)和对应的地址族关系如下:

协议族地址族描述
PF_UNIXAFUNIXUNIX 本地域协议族
PF_INETAF_INETTCP/IPv4 协议族
PF_INET6AF_INET6TCP/IPv6 协议族

PF_*AF_* 都定义在 bits/socket.h 头文件中,前后者的值完全相同,因此二者可以混用。

sa_data 成员用于存放 socket 地址值,但是不同的协议族的地址值具有不同的含义和长度:

协议族地址值含义和长度
PF_UNIX文件的路径名,长度可达到 108 字节
PF_INET16 bit 端口号和 32 bit IPv4 地址,共 6 字节
PF_INET616 bit 端口号,32 bit 流标识,128 bit IPv6 地址,32 bit 范围 ID ,共 26 字节

由上表可知 14 字节的 sa_data 根本无法容纳多数协议族的地址,因此 Linux 定义了新的通用 socket 地址结构体:

#include<bits/socket.h>
struct sockaddr_storage {sa_family_t sa_family;unsigned long int__ss_align;char__ss_padding[128-sizeof(__ss_align)];  // 地址是对齐的
}

3. 专用 socket 地址

上面两个通用的 socket 地址结构体显然很不好用,比如设置与获取 IP 地址和端口号就需要执行繁琐的位操作,所以 Linux 为各个协议族提供了专门的 socket 地址结构体:

  • UNIX 本地域协议族:
    #include<sys/un.h>
    struct sockaddr_un {sa_family_t sin_family;  // 地址族:AF_UNIXchar sun_path[108];  // 文件路径名
    };
    
  • TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用 socket 地址结构体:
    struct sockaddr_in { sa_family_t sin_family;  // 地址族:AF_INETu_int16_t sin_port;  // 端口号,要用网络字节序表示struct in_addr sin_addr;  // IPv4地址结构体,见下面
    };
    struct in_addr { u_int32_t s_addr;  // IPv4地址,要用网络字节序表示
    };struct sockaddr_in6 { sa_family_t sin6_family;  // 地址族:AF_INET6u_int16_t sin6_port;  // 端口号,要用网络字节序表示u_int32_t sin6_flowinfo;  // 流信息,应设置为0struct in6_addr sin6_addr;  // IPv6地址结构体,见下面u_int32_t sin6_scope_id;  // scope ID,尚处于实验阶段 
    }; 
    struct in6_addr { unsigned char sa_addr[16];  // IPv6地址,要用网络字节序表示
    };
    

所有专用 socket 地址(以及 sockaddr_storage)类型的变量在实际使用时都需要转化为通用 socket 地址类型 sockaddr(强制转换即可),因为所有 socket 编程接口使用的地址参数的类型都是 sockaddr 。

4. IP 地址转换函数

在计算机中使用 IP 地址,需要转换为二进制;而在记录日志中,则需要转换为供人可读的字符串:

// 老版本
#include<arpa/inet.h>
in_addr_t inet_addr(const char*strptr);  // 将点分十进制的ip地址转换为网络字节序表示的地址,失败时返回INADDR_NONE
int inet_aton(const char*cp,struct in_addr*inp);  // 与上一个相同,但是将转化结果存储在inp指向的地址中,成功时返回1,失败时返回0
char*inet_ntoa(struct in_addr in);  // 将网络字节序地址转换为点分十进制,函数内部用一个静态变量存储结果,返回值指向静态内存,因此不可重入char*szValue1=inet_ntoa(“1.2.3.4”);
char*szValue2=inet_ntoa(“10.194.71.60”);
printf(“address 1:%s\n”,szValue1);  // address1:10.194.71.60,被第二局覆盖了
printf(“address 2:%s\n”,szValue2);  // address1:10.194.71.60// 新版本
#include<arpa/inet.h>
int inet_pton(int af,const char*src,void*dst);  // 十(六)进制字符串IP转网络字节序,并把结果存入dst指向的内存,af指定地址族(不支持unix),成功返回1,失败返回0
const char*inet_ntop(int af,const void*src,char*dst,socklen_t cnt);  // 与上一条相反,cnt指定目标存储单元的大小,成功时返回目标存储单元地址,失败返回null,并设置errno#include<netinet/in.h>
#define INET_ADDRSTRLEN 16  // 利用宏指定cnt大小,对应IPv4
#define INET6_ADDRSTRLEN 46  // 对应IPv6

errno 是 Linux 提供的错误代码。

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...