【Linux 25】网络套接字 socket 概念

文章目录

  • 🌈 一、IP 地址概念
    • ⭐ 1. IP 地址的作用
    • ⭐ 2. 源 IP 地址和目的 IP 地址
  • 🌈 二、端口号概念
    • ⭐ 1. 源端口号和目的端口号
    • ⭐ 2. 端口号范围划分
    • ⭐ 3. 端口号 VS 进程 ID
    • ⭐ 4. 套接字 socket 的概念
  • 🌈 三、传输层的典型代表协议
    • ⭐ 1. TCP 协议
    • ⭐ 2. UDP 协议
    • ⭐ 3. 如何选择 TCP 还是 UDP
  • 🌈 四、网络字节序
    • ⭐ 1. 网络中的大小端
    • ⭐ 2. 网络字节序采用大端方式存储
    • ⭐ 3. 网络字节序与主机字节序之间的转换
  • 🌈 五、socket 编程接口
    • ⭐ 1. socket 常见函数
    • ⭐ 2. sockaddr 结构介绍

🌈 一、IP 地址概念

⭐ 1. IP 地址的作用

  • 互连网上的每台主机都有一个唯一的 IP 地址,总的来说就是,IP 地址在网络中用来标识主机的唯一性

⭐ 2. 源 IP 地址和目的 IP 地址

  • 如果想将一台主机 A 的数据传输到另一台主机 B 上,发送数据的 A 主机的 IP 地址就是源 IP 地址,而接受数据的对端主机 B 的 IP 地址就应该作为该数据传输时的目的 IP 地址。
    • 例:唐僧取经时,会根据他所持有的源 IP 地址 (东土大唐) 以及目的 IP 地址 (西天),在取经路上不停的问路,中间走过的每一站都是为了更加靠近目的 IP 地址。
    • 只要有了 IP 地址,数据报文就不会走进不在源 IP 地址和目的 IP 地址之间的其他局域网。
  • 在数据进行传输前,会先自定向下贯穿网络协议栈完成数据的封装,其中在网络层封装的 IP 报头中就包含了该数据的源 IP 地址和目的 IP 地址。

🌈 二、端口号概念

⭐ 1. 源端口号和目的端口号

  • 主机之间进行通信并不仅是为了将数据发送给对端主机而已,那没有任何意义。主机之间进行通信是为了访问对端主机上的某个服务。
    • 用户 a 在 A 主机上使用 qq 给用户 b 的主机 B 中的 qq 发送数据,不是就将这段数据发给主机 B 就完了。
    • 通信的根本目的是为了实现人与人之间的通信,用户 a 从 qq 上发送给用户 b 的消息,需要让用户 b 也能在 qq 上看到才行。
    • 但是用户手里的主机上有那么多进程,没人知道发送的数据应该交给主机上的哪个进程。
    • 同时,如果用户 b 想要给用户 a 回消息,发送的数据也需要能够找到用户 a 手里的主机中的 qq 这个程序才行。
  • 因此,端口号是用来唯一标识主机中的进程
  • 真正的通信是两个主机上的两个进程在进行通信,而源端口号和目的端口号就是用来找到通信双方的主机中的那个用来通信的进程

image-20241026103730933

⭐ 2. 端口号范围划分

  1. 知名端口号 (0 ~ 1023),像 HTTP、FTP、SSH 等广泛使用的应用层协议的端口号都是固定的。
    • 这些端口号和其提供的服务基本上已经算是一个东西了,只要知道这些端口号,就能知道对应提供的是什么服务。
    • 就像 120、110、119 这些电话和与其绑定的服务一样,看到这些电话就知道对应的是啥服务。
  2. 操作系统动态分配端口号 (1024 ~ 65535),由操作系统动态分配的端口号,客户端进程的端口号由操作系统从这个范围分配。

⭐ 3. 端口号 VS 进程 ID

  • 端口号和进程 IP 都能用来唯一标识一台主机上的某个进程,但在网络通信中,并不能用进程 ID 来替代端口号

1. 为什么不能用进程 PID 替代网络端口号 port

  1. 端口号属于网络的概念,进程 ID 用来标识系统内进程的唯一性,它属于系统级的概念;而端口号用来标识需要对外进行网络数据请求的进程的唯一性,它属于网络的概念。
  2. 不是所有的进程都要进行网络通信,一台主机上存在着 n 个进程,但不是所有的进程都要进行网络通信的,但每个进程都要有自己的 PID。这种情况下就不太适合使用 PID 来标识网络进程的唯一性了。
  3. 专事专办,在不同的场景下可能需要不同的编号来标识某种事物的唯一性,某些编号会更加适用于某种场景。
    • 如:身份证号已经足够标识身份的唯一性了,但还是有学号和工号这种特殊编号用来标识在不同场景下的唯一身份。
  4. 实现系统和网络的解耦 (最重要),进程在每次启动时,进程 PID 都会发生变化。如果使用 PID 代替端口号,会直接导致网络部分也需要作出调整。

2. 如何通过端口号 port 找到对应的进程

  • 在底层中,采用哈希的方式建立了端口号和进程 PID 之间的映射关系
  • 当底层拿到端口号时,就可以执行对应的哈希算法,然后拿到与该端口号对应的进程 PID,从而找到对应进程。

⭐ 4. 套接字 socket 的概念

  • IP 地址用来标识网络中唯一的一台主机,而端口号 port 则用来标识该主机上唯一的一个网络进程。
    • 因此,使用 ip + port 就能标识互联网中唯一的一个进程
  • 网络通信,本质上是在用两个互联网进程代替人来进行通信,通过 { 源 ip,源 port,目的 ip,目的 port } 即可标识互联网中唯二的两个进程。
    • 因此,网络通信的本质就是进程间通信
  • 将 ip + port 的组合叫做 socket 套接字

理解 socket 这个名词

  • socket 翻译成中文有 ⌈ 插座 ⌋ 的意思,插座上有不同规格的插孔,将插头插入到对应的插孔当中就能够实现电流的传输。
  • 在进行网络通信时,客户端就相当于插头,服务端就相当于一个插座,但服务端上可能会有多个不同的服务进程 (多个插孔)。因此当访问服务时需要指明服务进程的端口号 (对应规格的插孔),才能享受对应服务进程的服务。

🌈 三、传输层的典型代表协议

  • 网络协议栈贯穿整个网络体系结构,在应用层中,操作系统层和驱动层各自占有一部分网络协议。
  • 传输层写在操作系统中,当使用系统提供的接口实现网络通信时,必须要面对的就是传输层的协议,传输层最典型的协议是 TCP 和 UDP 。

⭐ 1. TCP 协议

  • 传输控制协议 TCP (Transmission Control Protocol) 是一种面向连接的可靠的基于字节流的传输层通信协议。

TCP 协议的特点

  1. TCP 协议是面向连接的:当两台主机之间想要进行数据传输时,需要先建立连接。只有在连接建立成功后才可以进行数据传输。
  2. TCP 协议是保证可靠的:数据在传输过程中如果出现了丢包、乱序等情况,TCP 协议都有对应的解决办法。

⭐ 2. UDP 协议

  • 用户数据报协议 UDP (User Datagram Protocol) 是一种无需建立连接的不可靠的面向数据包的传输层通信协议。

UDP 协议的特点

  1. UDP 协议不需要建立连接:当两台主机想要进行数据传输时,直接将数据包发送给对端主机即可。
  2. UDP 协议是不保证可靠的:由于特点 1,UDP 协议是不可靠的。UDP 协议不知道数据在传输过程中是否出现了丢包、乱序等情况。

⭐ 3. 如何选择 TCP 还是 UDP

1. 不应将 UDP 协议的特点当作缺陷

  • UDP 不保证可靠并不是缺陷,而是特点。
  • UDP 不保证可靠意味着要做的工作比 TCP 少,实现起来比 TCP 简单,且数据传输速度更快。

2. 如何选择通信协议

  • 编写网络通信代码时,应根据上层的应用场景选择 TCP / UDP 协议。
  • 当应用场景严格要求数据在传输过程中的可靠性时,选择 TCP 协议。
  • 当应用场景允许数据传输出现少量丢包时,优先选择简单的 UDP 协议。

🌈 四、网络字节序

⭐ 1. 网络中的大小端

  • 大端模式:数据的高位字节处的内容存放在内存的低地址处,而数据的低位字节处的内容存放在内存的高地址处。
  • 小端模式:数据的高位字节处的内容存放在内存的高地址处,而数据的低位字节处的内容存放在内存的低地址处。

image-20241026152047117

⭐ 2. 网络字节序采用大端方式存储

  • 如果程序只在本地机器上运行,由于同一台机器的数据的存储方式一致,因此无需考虑数据的大小端存储问题。
  • 如果程序涉及到网络通信,则需要考虑大小端的转换问题,否则接收端主机识别出的数据可能与发送端发送的数据不一致。
  • 由于不能保证通信双方存储数据的方式一致,那么就只能统一网络字节序,TCP / IP 协议规定,网络数据流采用大端字节序
    • 如果 发送端 是 小 端存储,需要先将数据转换成大端,然后发送到网络中。
    • 如果 发送端 是 大 端存储,可以直接将数据发送到网络中。
    • 如果 接收端 是 小 端存储,需要先将接收到的数据转换成小端,然后进行识别。
    • 如果 接收端 是 大 端存储,可以直接识别通过网络传输过来的数据。

⭐ 3. 网络字节序与主机字节序之间的转换

  • 为了让网络程序具备可移植性,使得同样的 C 代码在 大端 / 小端 机上都能运行,系统提供了4 个函数用于实现网络字节序和主机字节序之间的转换。
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);	// 将 32 位的 主机字节序 转换为 32 位的 网络字节序
uint16_t htons(uint16_t hostshort);	// 将 16 位的 主机字节序 转换为 16 位的 网络字节序
uint32_t ntohl(uint32_t netlong);	// 将 32 位的 网络字节序 转换为 32 位的 主机字节序
uint16_t ntohs(uint16_t netshort);	// 将 16 位的 网络字节序 转换为 16 位的 主机字节序
  • 函数名看着挺混乱,但还是有规律的,h 表示 host,n 表示 network,l 表示 32 位长整数,s 表示 16 位短整数。
    • 例:htonl 表示的就是将 32 位的主机字节序转换成 32 位的网络字节序,其余同理。
  • 如果主机采用的是小端存储方式,这些函数就会将提供参数做相应的大小端转换,然后返回转换后的大端字节序。
  • 如果主机采用的是大端存储方式,这些函数就不会进行转换,而是直接将参数返回。

🌈 五、socket 编程接口

⭐ 1. socket 常见函数

  1. 创建套接字
int socket(int domain, int type, int protocol);
  1. 绑定端口号
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  1. 监听套接字
int listen(int sockfd, int backlog);
  1. 接受请求
int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
  1. 建立连接
int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);

⭐ 2. sockaddr 结构介绍

  • socket 不仅支持跨网络的进程间通信,还支持本主机的进程间通信。
  • 在创建套接字时,需要选择创建的是用于网络通信的网络套接字,还是用于本地通信的域间套接字。
  • 由于在进行网络通信时,需要传递 ip + port,而本地通信则不需要。因此套接字就提供了用于网络通信sockaddr_in 结构体,以及用于本地通信sockaddr_un 结构体。
  • 而为了让网络通信和本地通信都能使用同一个函数,又出现了一种新的结构体 sockaddr,这 3 种结构体的前面 16 个比特位相同,都叫做协议家族。
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);	in_port_t sin_port;			// 端口号struct in_addr sin_addr;	// IP 地址/* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr)- __SOCKADDR_COMMON_SIZE- sizeof (in_port_t)- sizeof (struct in_addr)];
};

image-20241026160322445

  • 在使用 socket 相关函数时,不管要进行的是网络通信还是本地通信,统一传入 sockaddr 结构体作为 socket 相关函数的参数。
  • 通过设置 sockaddr 的协议家族来决定进行的是网络通信还是本地通信,socket 相关函数会提取出 sockaddr 的前 16 个比特位来判断要进行的是本地还是网络通信。
  • 在使用 socket 相关函数时,不管要进行的是网络通信还是本地通信,统一传入 sockaddr 结构体作为 socket 相关函数的参数。
  • 通过设置 sockaddr 的协议家族来决定进行的是网络通信还是本地通信,socket 相关函数会提取出 sockaddr 的前 16 个比特位来判断要进行的是本地还是网络通信。
  • 编写网络通信代码时,定义的依旧是 sockaddr_in 结构体;传参时,需要将定义的 sockaddr_in 结构体变量的地址类型强转为 sockaddr*

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462992.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用Docker Compose构建微服务架构

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 利用Docker Compose构建微服务架构 引言 Docker Compose 简介 安装 Docker Compose 创建项目结构 编写 Dockerfile 前端 Dockerf…

【Vue】一个案例带你学会组件通信!!!(1)(父传子props+子传父$emit)

嘿&#xff0c;开发者们&#x1f44b;&#xff01;欢迎来到今天的Vue.js组件通信大冒险。你是否曾在父子组件间的数据同步问题上感到头疼&#xff1f;&#x1f92f; 今天&#xff0c;我们将一起揭开Vue.js父子通信的神秘面纱&#xff0c;学习如何让数据在父子组件间流畅地“跳舞…

在VS中安装chatGPT

2、在VSCode中打开插件窗口 3、输入ChatGPT 4、这里有个ChatGPT中文版&#xff0c;就它了 5、安装 6、这时候侧边栏多了一个chatGPT分页图标&#xff0c;点击它 7、打个招呼 8、好像不行 9、看一下细节描述 10、根据要求按下按下快捷键 Ctrl Shift P 11、切换成国内模式 12、…

3. keil + vscode 进行stm32协同开发

1. 为什么使用vscode 主要还是界面友好&#xff0c;使用习惯问题&#xff0c;vscode 从前端&#xff0c;js, c/c, qt, 仓颉&#xff0c;rust都有很好插件的支持&#xff0c;并且有romote&#xff0c; wsl 等很多插件可以提高效率&#xff0c; 唯一的问题就是要使用插件进行环境…

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记&#xff1a;PostgreSQL 主从复制 博客地址&#xff1a;TMDOG 的博客 在现代应用程序中&#xff0c;数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能&#xff0c;可以在多个数据库实例之间复制数据&#xff0c;以实现冗余和负载均衡。本…

433、315通信、ev1527、2262编码

目录 ASK介绍EV1527编码芯片介绍模块介绍无线发射芯片无线接收芯片解码程序发射电路原理图 ASK介绍 ASK是幅移键控&#xff0c;通过调幅将数据发送出去&#xff0c;所以发送与接收都是多位二进制数。 ASK如何区分0和1&#xff1f; 0&#xff1a;发送 433.92Mhz 无线波形&…

Python 5个数据容器

列表&#xff08;list&#xff09; 特点&#xff1a;可以被修改 列表的定义 定义空列表&#xff1a; 变量名 [] 或 变量名 list() 定义变量&#xff1a; 变量名 [元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;... ] 取出列表元素 列表名 [下标索引] 从前向…

复习数据库(约束)上篇

目录 约束的分类 分类 注意 主键约束 添加主键约束 1 建表时&#xff0c;添加 1.1创建表&#xff1a;定义列时指定 1.2 创建表&#xff1a;定义列之后独立指定主键&#xff1a; 2 建表后使用alter 关键字添加 删除约束 在主键添加自动增长属性 疑问 1 建表时添加 …

国内短剧源码短剧系统搭建小程序部署H5、APP打造短剧平台

​在当今的互联网时代&#xff0c;短剧作为一种新兴的娱乐形式&#xff0c;受到了越来越多用户的喜爱。为了提供更好的用户体验和满足用户需求&#xff0c;一个好的短剧系统需要具备多元化的功能和优质的界面设计。 本文将介绍国内短剧源码短剧系统搭建小程序部署H5、APP所需的…

Python(数据结构2)

常见数据结构 队列 队列(Queue)&#xff0c;它是一种运算受限的线性表,先进先出(FIFO First In First Out) Python标准库中的queue模块提供了多种队列实现&#xff0c;包括普通队列、双端队列、优先队列等。 1 普通队列 queue.Queue 是 Python 标准库 queue 模块中的一个类…

QT 机器视觉 (3. 虚拟相机SDK、测试工具)

本专栏从实际需求场景出发详细还原、分别介绍大型工业化场景、专业实验室场景、自动化生产线场景、各种视觉检测物体场景介绍本专栏应用场景 更适合涉及到视觉相关工作者、包括但不限于一线操作人员、现场实施人员、项目相关维护人员&#xff0c;希望了解2D、3D相机视觉相关操作…

QT打包Macosx应用发布App Store简易流程

1、QC里编译工程&#xff0c;生成Release版的的app文件&#xff1b; 2、运行macdeployqt把需要的文件打包进app文件中&#xff1b; % ~/Qt/5.15.0/clang_64/bin/macdeployqt {编译的app文件所在路径}/Release/xxxx.app 3、使用codesign对app进行签名&#xff0c;如果要发App…

Android平台RTSP转RTMP推送之采集麦克风音频转发

技术背景 RTSP转RTMP推送&#xff0c;好多开发者第一想到的是采用ffmpeg命令行的形式&#xff0c;如果对ffmpeg比较熟&#xff0c;而且产品不要额外的定制和更高阶的要求&#xff0c;未尝不可&#xff0c;如果对产品稳定性、时延、断网重连等有更高的技术诉求&#xff0c;比较…

网络:ARP的具体过程和ARP欺骗

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》《网络》 《redis学习笔记》 文章目录 前言ARP具体过程ARP欺骗原理总结 前言 本文仅作为ARP具体过程和ARP欺骗的知识总结 硬件类型 &#xff1a;指定发送和接受ARP包的硬件类型&am…

单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构

目录 一、合并两个有序链表 二、链表分割 三、链表的回文结构 u解题的总体思路&#xff1a; 合并两个有序链表&#xff1a;首先创建新链表的头节点&#xff08;哨兵位&#xff1a;本质上是占位子&#xff09;&#xff0c;为了减少一些判断情况&#xff0c;简化操作。然后我们…

整理 【 DBeaver 数据库管理工具 】的一些基础使用

目录 连接设置切换工作空间SQL编辑器&#xff08;写sql语句&#xff09;打开方式新建查询&#xff08;sql编辑器&#xff09;打开写的 sql 查询&#xff08;项目浏览器&#xff09; 备份sql文件查看历史执行语句自动保存sql语句的文件&#xff08;编辑器&#xff09;关闭自动生…

Android Studio 依赖仓库地址

在Android Studio进行开发时&#xff0c;会遇到依赖库下载慢或者老项目使用的依赖库找不到的问题&#xff0c;折腾了两天&#xff0c;终于找到解决方法&#xff0c;使用 阿里云云效Maven&#xff0c;地址&#xff1a;仓库服务https://developer.aliyun.com/mvn/guide &#xff…

51单片机教程(五)- LED灯闪烁

1 项目分析 让输入/输出口的P1.0或P1.0~P1.7连接的LED灯闪烁。 2 技术准备 1、C语言知识点 1 运算符 1 算术运算符 #include <stdio.h>int main(){// 算术运算符int a 13;int b 6;printf("%d\n", ab); printf("%d\n", a-b); printf("%…

MySQL日志——针对实习面试

目录 MySQL日志MySQL有哪些日志&#xff1f;请解释一下MySQL的二进制日志&#xff08;Binlog&#xff09;的作用&#xff1f;复制&#xff08;Replication&#xff09;数据恢复&#xff08;Point-in-Time Recovery&#xff09; Binlog日志的三种格式是什么&#xff1f;如何使用…

STM32 HAL库 SPI驱动1.3寸 OLED屏幕

目录 参考硬件引脚与接线 点亮屏幕CubeMX 配置OLED 驱动程序代码 参考 基于STM32F103C8T6最小系统板HAL库CubeMX SPI驱动7针 OLED显示屏&#xff08;0.96寸 1.3寸通用&#xff09;0.96 oled HAL库驱动 SPI STM32SPI驱动0.96/1.3寸 OLED屏幕&#xff0c;易修改为DMA控制STM32驱…