Linux socket编程(1):套接字、字节序和地址结构体

套接字(socket)是一种使用标准Unix文件描述符与其他程序进行通信的方式,它在实际的应用中都十分常用。所以从这一篇文章开始,我将详细介绍一下Linux环境下的socket的用法。本篇文章将介绍套接字、字节序和地址结构体的相关知识。

文章目录

  • [1 什么是套接字](#1 什么是套接字)
  • [2 字节序](#2 字节序)
  • [3 地址结构体](#3 地址结构体)

1 什么是套接字

计算机网络由多个层组成,每个网络层提供关于该层数据的不同限制。而套接字的本意是提供一种进程间通信的方法,使得在相同或不同主机上的进程能够以相同的规范进行双向的信息传送。如下图所示,套接字接口提供了对网络下层(1-4层)的统一API,并能套接字应用程序中实现上层(5-7层和应用格式)功能。

套接字是一种通用的编程接口,可以用于与不同类型的网络协议进行交互,不仅仅限于IP协议,还有UDP、ICMP等。在实际应用中,套接字应用程序通常会依赖于IP协议来实现网络通信。在传输层,套接字支持两种特定的协议:TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)。其中,TCP是面向连接、可靠、有序的流协议,而UDP是无连接、不可靠、自我界定的数据报协议。

在Linux中,Layer2-Layer4已经由内核实现,所以套接字可以看做是内核提供的给用户使用的网络协议栈的编程接口。

2 字节序

端口号和IP地址由多字节数据类型表示,它们被放置在数据包中,用于路由和多路复用。端口号占据2个字节,IPv4地址占据4个字节,但在不同架构之间传输多字节数据类型时会出现问题。

大端(Big-Endian)和小端(Little-Endian)是两种不同的字节序方式,用于表示多字节数据类型(如整数、浮点数)在计算机内存中的存储方式。

  • 大端字节序:MSB(最高有效位)位于地址最低的内存单元
  • 大端字节序:LSB(最低有效位)位于地址最低的内存单元

如下图所示,一个64位的值0x1122334455667788,在小端机器的内存中为0x8877665544332211,而在大端机器的内存中为0x1122334455667788。

如下图所示,可以通过程序来判断计算机的字节序:

在网络协议中,使用的是大端字节序,而大部分的主机使用的是小端字节序。所以,在Socket编程中提供了下面的函数来更改IP和端口号的字节序:

1.转换端口号(16位的整数)
Host->Network:主机字节序转网络字节序
unit16_t htons(uint16_t hostportnumber)
Network->Host:网络字节序转主机字节序
unit16_t ntohs(uint16_t netportnumber)

2.转换IPV4地址(32位的整数)
Host->Network
unit32_t htonl(uint32_t hostportnumber)
Network->Host
Unit32_t ntohl(uint32_t netportnumber)

3 地址结构体

connect()accept()bind()等套接字函数需要使用明确定义的地址结构来保存IP地址信息、端口号和协议类型。我们使用套接字来编写使用不同协议的网络应用程序,比如我们可以使用IPV4、IPV6、Unix等。问题在于:每种不同的协议都使用不同的地址结构来保存其寻址信息。

我们有存在一个通用的地址结构:struct sockaddr,在传递给这些套接字函数时,必须将您特定于协议的地址结构强制转换为通用的地址结构。

特定于协议的地址结构通常以sockaddr_开头,并以取决于该协议的后缀结尾。如下:

  1. struct sockaddr_in:
    • sockaddr_in 结构用于表示IPv4地址,通常称为"Internet地址"。它包含 IP 地址、端口号和协议族信息。这是在IPv4网络编程中最常使用的结构。
  2. struct sockaddr_in6:
    • sockaddr_in6 结构用于表示IPv6地址,与 sockaddr_in 类似,但适用于IPv6网络编程。它包含IPv6地址、端口号和协议族信息。
  3. struct sockaddr_un:
    • sockaddr_un 结构用于表示本地Unix套接字地址。Unix域套接字是用于本地通信的一种方式,而不是通过网络进行通信。它包含套接字文件的路径信息。
  4. struct sockaddr_dl:
    • sockaddr_dl 结构用于表示数据链路层地址,通常在底层网络编程中使用。这包括硬件地址,如MAC地址。这通常用于需要直接访问底层网络的应用程序。

本篇文章仅介绍IP4地址结构:struct sockaddr_in,来看一下它的结构体成员:

struct sockaddr_in {
    sa_family_t    sin_family; /* address family: AF_INET */
    in_port_t      sin_port;   /* port in network byte order */
    struct in_addr sin_addr;   /* internet address */
};

/* Internet address */
struct in_addr {
	uint32_t       s_addr;     /* address in network byte order */
};
  • sin_family:地址结构的类型,在这里固定设置为 AF_INET,表示这是一个IPv4地址结构
  • sin_port:端口号
  • struct in_addr sin_addr:IPv4地址信息的结构体,该结构体中使用s_addr存储32位的IPv4地址

我们平时使用的地址都是192.168.1.1这种类型的,如果要转换为s_addr类型的整数,我们可以使用inet_addrinet_aton将点分十进制字符串表示的IPv4地址转换为网络字节顺序的32位整数。

  • inet_addr已经过时了,建议使用inet_aton ,因为它可以提供更多的错误处理信息

反过来,我们可以使用inet_ntoa()将32位的网络字节顺序的整数表示的IPv4地址转换为点分十进制字符串。

相关推荐
一个不秃头的 程序员1 小时前
服务器上加入SFTP------(小白篇 1)
运维·服务器
fnd_LN1 小时前
Linux文件目录 --- 复制命令CP、递归复制目录、软连接、硬链接
linux·运维·服务器
MorleyOlsen1 小时前
【Trick】解决服务器cuda报错——RuntimeError: cuDNN error: CUDNN_STATUS_NOT_INITIALIZED
运维·服务器·深度学习
周周的奇妙编程1 小时前
基于鲲鹏服务器的打砖块小游戏部署
运维·服务器
从后端到QT1 小时前
boost asio 异步服务器
服务器·网络·tcp/ip
墨水\\2 小时前
Ansible部署及基础模块
服务器·网络·ansible
七七powerful2 小时前
ansible play-book玩法
linux·服务器·ansible
晚安,cheems2 小时前
linux的权限
linux·运维·服务器
路溪非溪2 小时前
Linux加载一个应用程序的过程总结
linux·运维·服务器
不吃鱼的羊2 小时前
Excel生成DBC脚本源文件
服务器·网络·excel