【Linux网络】认识协议(TCP/UDP)、Mac/IP地址和端口号、网络字节序、socket套接字

头像
⭐️个人主页:@小羊
⭐️所属专栏:Linux
很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

动图描述

目录

    • 1、初识协议
    • 2、UDP、TCP
    • 3、Mac、IP地址
    • 4、端口号
    • 5、网络字节序
    • 6、socket


1、初识协议

  • 协议就是一种约定。
  • 如何让不同厂商生产的计算机之间能够互相通信?需要由权威组织或公司制定网络协议。
  • 协议本质也是软件,在设计上为了更好的进行模块化,解耦合,因此被设计为层状结构。

协议本质也是软件,为了更好的模块换,降低耦合度,所以被设计为层状结构。在Linux网络协议栈中,各个层次协同工作,以实现数据的封装、传输、路由和接收。从底层到高层,这些层次包括:

  1. 链路层(数据链路层):负责物理网络上的数据传输,包括帧的封装、错误检测和纠正等。在Linux中,这一层通常与特定的网络接口卡(NIC)驱动程序相关联。

  2. 网络层:提供IP地址管理和路由功能,确保数据包能够正确地从一个网络传输到另一个网络。Linux支持IPv4和IPv6两种IP协议版本。

  3. 传输层:提供端到端的通信服务,确保数据的可靠传输或快速、不可靠的传输。TCP(传输控制协议)提供可靠的数据传输,而UDP(用户数据报协议)则提供无连接的数据传输服务。

  4. 应用层:提供用户和网络服务之间的接口,包括HTTP(用于Web浏览)、SMTP(用于电子邮件发送)、FTP(用于文件传输)等多种应用层协议。

一般而言:

  • 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容
  • 对于一台路由器,它实现了从网络层到物理层
  • 对于一台交换机,它实现了从数据层到物理层
  • 对于一台集线器,它只实现了物理层

2、UDP、TCP

传输层的典型代表:

TCP协议UDP协议
传输层协议传输层协议
有连接无连接
可靠传输不可靠传输
面向字节流面向数据报

TCP协议格式:
在这里插入图片描述

  • 确认应答至少应该是一个完整的TCP报头
  • 确认序号 = 序号 + 1,表示该序号之前的内容被全部收到了
  • 为什么要有序号和确认序号两个序号,并且是独立的字段?
    TCP报文,大多数情况下既是应答,又是数据,即捎带应答机制,这个时候序号和确认序号这两个字段要被同时使用。

TCP 将每个字节的数据都进行了编号,即为序列号。每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据,下一次你从哪里开始发。

  • 4位首部长度:这个字段的单位是4字节,取值范围是0到15,乘以4后得到报头的实际字节长度范围是20到60字节。当首部长度为5时,表示的是标准的20字节报头。

6 位标志位:用于区分报文类型

标志位说明
URG紧急指针是否有效,需要优先处理的报文
ACK表明自己是应答报文
PSH提示接收端应用程序立刻从 TCP 缓冲区把数据读走
RST对方要求重新建立连接,我们把携带 RST 标识的称为复位报文段
SYN请求建立连接,我们把携带 SYN 标识的称为同步报文段
FIN通知对方,本端要关闭了,我们称携带 FIN 标识的为结束报文段
  • 16位窗口大小流量控制,由接收缓冲区剩余空间大小决定,由滑动窗口实现
  • 超时重传:在TCP连接中,当发送方发送一个数据段后,会启动一个超时计时器,如果在计时器超时之前,发送方没有收到接收方的确认(ACK)报文,那么发送方就会认为该数据段已经丢失,并重新发送该数据段,直到收到确认报文或达到重传次数限制为止。

在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接。

在这里插入图片描述

为什么要三次握手?四次挥手?

  1. 建立双方主机通信的意愿共
  2. 双方验证全双工信道的通畅性
  3. 本质是四次握手,因为捎带应答机制变为三次握手
  4. Tcp是全双工的,要关闭两个朝向上的连接

我们测试时有时会出现bind error,是什么原因?

  • TCP 协议规定,主动关闭连接的一方要处于 TIME_ WAIT 状态,等待两个MSL(一般为2分钟)的时间后才能回到 CLOSED 状态
  • 我们使用 Ctrl-C 终止了 server,所以 server 是主动关闭连接的一方,在TIME_WAIT 期间仍然不能再次监听同样的 server 端口

如何解决?

  • 使用 setsockopt()设置 socket 描述符的选项 SO_REUSEADDR 为 1,表示允许创建端口号相同但 IP 地址不同的多个 socket 描述符
int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  • CLOSE_WAIT状态则是被动关闭连接的一方在接收到FIN报文并发送ACK后的状态
  • 如果服务器不关闭sockfd,则只会完成两次挥手,服务器就会长时间处于close_wait状态。

滑动窗口:

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值
  • 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有确认应答过的数据,才能从缓冲区删掉
  • 窗口只能向右滑动,且根据对方接收缓冲区的大小调整大小
    在这里插入图片描述

丢包重传问题:

  • 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答,则说明我们只收到了 “1001” 之前的报文,在这种情况下,发送方不等待超时定时器的触发,而是立即重传该丢失的数据包,即将对应的数据 1001 - 2000 重新发送。这种机制被称为 "高速重发控制”(快重传)

拥塞控制:

  • 虽然 TCP 滑动窗口能够高效可靠的发送大量的数据,但是如果刚开始就发送大量的数据,仍然可能引发问题。因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵,在不清楚当前网络状态下,贸然发送大量的数据,很有可能雪上加霜。
  • TCP引入慢启动机制,即先发少量的数据探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据
    在这里插入图片描述

Tcp通过校验和、序列号(按序到达、去重)、确认应答、超时重发、连接管理、流量控制、拥塞控制等保证可靠性;通过滑动窗口、快速重传、延迟应答、捎带应答等提高性能。


UDP协议格式:
在这里插入图片描述

  • 无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接;

  • 不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息;

  • 面向数据报:不能够灵活的控制读写数据的次数和数量;

  • 16 位 UDP 长度,表示整个数据报(UDP 首部+UDP 数据)的最大长度,如果要传输的数据超过 64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装;

  • 如果校验和出错,就会直接丢弃;

  • UDP协议的报头是固定的8字节,所以协议的接收方直接截取前8个字节的报头,剩下的就是有效数据。

UDP的缓冲区:

  • 发送缓冲区:UDP 没有真正意义上的发送缓冲区,调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  • 接收缓冲区:UDP的接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致,如果缓冲区满了,再到达的 UDP 数据就会被丢弃;

TCP/UDP 对比:

  • 无论是Tcp有连接Udp无连接,还是Tcp可靠Udp不可靠,这都是它们的特性,不是优缺点,它们适用于不同的需求场景
  • TCP 用于可靠传输的情况,应用于文件传输,重要状态更新等场景
  • UDP 用于对高速传输和实时性要求较高的通信领域,例如早期的 QQ、视频传输、广播等

3、Mac、IP地址

每台主机在局域网上,要有唯一的标识来保证主机的唯一性:mac 地址

以太网中,任何时刻,只允许一台机器向网络中发送数据。如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞,所有发送数据的主机要进行碰撞检测和碰撞避免,没有交换机的情况下,一个以太网就是一个碰撞域,局域网通信的过程中,主机对收到的报文确认是否是发给自己的,是通过目标mac地址判定的。

其中每层都有协议,当我们进行传输流程的时候,要进行封装和解包:
在这里插入图片描述
Tcp/IP通讯过程:
在这里插入图片描述

IP 地址是在 IP 协议中, 用来标识网络中不同主机的地址,对于 IPv4 来说, IP 地址是一个 4 字节,32 位的整数,我们通常也使用 “点分十进制” 的字符串表示 IP 地址, 例如1.94.9.200,用点分割的每一个数字表示一个字节,范围是 0 - 255。

在这里插入图片描述

Mac地址 vs IP地址:
唐僧从东土大唐出发,要去西天拜佛求经,途中要经过女儿国和黑风岭,女儿国和黑风岭是相邻两地。

  • 东土大唐 -> 西天:源IP地址 -> 目的IP地址
  • 女儿国 -> 黑风岭:源Mac地址 -> 目的Mac地址

其中经过的各个国家就是路由器,相邻的国家在同一个局域网中,路由器路由的下一个目的地是根据目的IP地址路由的,局域网通信需要Mac地址指路,一般Mac地址只在局域网中有效,IP地址几乎不变。

IP在网络中标识主机的唯一性,数据传输到主机不是目的而是手段,最终到达主机内的目的进程才是目的。但是在主机中,同一时间进程可能有很多,那怎么找到目的进程呢?


4、端口号

端口号(port)是传输层协议的内容,是一个2字节16位的整数,端口号标识唯一进程,一个端口号只能被一个进程占用

IP地址+端口号能够标识网络中的唯一进程。
网络通信,本质上也是进程间通信。

其中 0 - 1023 是知名端口号,HTTP, FTP, SSH等这些广为使用的应用层协议,它们的端口号都是固定的。1024 - 65535 是操作系统动态分配的端口号,比如客户端程序的端口号就是有操作系统动态分配的。

pid也可以标识唯一进程,为什么还要引入端口号呢?
进程pid属于系统概念,如果继续沿用pid标识唯一进程,会增加耦合度。另外,一个进程可以绑定多个端口号,但一个端口号不能被多个进程绑定。

网络通信的本质,也是进程间通信,本质是两个互联网进程代表人来进行通信。IP + port 叫做套接字socket。

一个进程可以 bind 多个端口号,但一个端口号不能被多个进程 bind。


5、网络字节序

内存中的多字节数据相对于内存地址有大端和小端之分,网络数据流同样有大端小端之分,如何定义网络数据流的地址?

  • 网络数据流的地址被规定:先发出去的是低地址,后发出去的是高地址。
  • TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。

为使网络程序具有可移植性,使用样的C代码在大端和小端机器上编译后都能正常运行,可以调用下面库函数做网络字节序主机字节序的转换。

#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t hostlong);
uint16_t ntohs(uint16_t hostshort);
  • h表示hostn表示networkl表示32位长整数,s表示16位短整数。

6、socket

socket常见API:

// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

socket:

  1. socket()打开一个网络通讯端口,如果成功,就像open()一样返回一个文件描述符,出错返回-1
  2. 应用程序可以像读写文件一样用 read/write 在网络上收发数据
  3. 对于 IPv4, family 参数指定为 AF_INET
  4. 对于 TCP 协议,type 参数指定为 SOCK_STREAM,表示面向流的传输协议
  5. protocol 参数指定为 0 即可

bind:

  1. bind()成功返回 0,失败返回-1
  2. bind()的作用是将参数 sockfd 和 myaddr 绑定在一起,使 sockfd 这个用于网络通讯的文件描述符监听 myaddr 所描述的地址和端口号
  3. struct sockaddr *是一个通用指针类型,myaddr 参数实际上可以接受多种协议的 sockaddr 结构体,而它们的长度各不相同,所以需要第三个参数 addrlen指定结构体的长度,我们可以对 myaddr 参数这样初始化:
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(_port);
local.sin_addr.s_addr = INADDR_ANY;

listen:

  1. listen()声明 sockfd 处于监听状态,并且最多允许有 backlog 个客户端处于连接
    等待状态,如果接收到更多的连接请求就忽略
  2. listen()成功返回 0,失败返回-1

accept:

  1. 三次握手完成后,服务器调用 accept()接受连接
  2. 如果服务器调用 accept()时还没有客户端的连接请求,就阻塞等待,直到有客户端
    连接上来
  3. addr 是一个传出参数,accept()返回时传出客户端的地址和端口号
  4. 如果给 addr 参数传 NULL,表示不关心客户端的地址
  5. addrlen 参数是一个传入传出参数(value-result argument),传入的是调用者提供的,缓冲区 addr 的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度

connect:

  1. 客户端需要调用 connect()连接服务器
  2. connect 和 bind 的参数形式一致,区别在于 bind 的参数是自己的地址,connect 的参数是对方的地址
  3. connect()成功返回 0,出错返回-1

注意:

  1. 由于客户端不需要固定的端口号,因此不必调用 bind(),客户端的端口号由内核自动分配
  2. 客户端不是不允许调用 bind(),只是没有必要显示的调用 bind()固定一个端口号,否则如果在同一台机器上启动多个客户端,就会出现端口号被占用导致不能正确建立连接
  3. 服务器也不是必须调用 bind(),但如果服务器不调用 bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦

sockaddr结构:

sock API是一层抽象的网络编程接口,适用于各种底层网络协议,各种网络协议的地址格式并不相同。

在这里插入图片描述
socket API 可以都用struct sockaddr*类型表示,在使用的时候需要强制转换成sockaddr_in,增加了程序的通用性。


本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

头像

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

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

相关文章

基于flask+vue框架的的医院预约挂号系统i1616(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:用户,医生,科室信息,就诊信息,医院概况,挂号信息,诊断信息,取消挂号 开题报告内容 基于FlaskVue框架的医院预约挂号系统开题报告 一、研究背景与意义 随着医疗技术的不断进步和人们健康意识的日益增强&#xff0c;医院就诊量逐年增加。传统的现场…

影刀RPA中级证书-Excel进阶-开票清单

1.操作题需求 请参照视频内容&#xff0c;将开票账单表格中的数据整理成开票清单。请下载 开票账单.xlsx 整理规则如下&#xff1a; 1. 金额为0的数据为赠品&#xff0c;无需开票&#xff0c;需删除2. 开票清单需要从开票账单中获取的数据包括有开票名称、数量、金额、税率&…

浅谈模组-相机鬼像

一&#xff0e;前言 在成像中&#xff0c;我们常常会遇到肉眼观测的真实世界中&#xff0c;不存在的异常光影出现在画面中&#xff0c;并伴有各种颜色&#xff0c;我们将这个物体称为鬼像。某些鬼像可能会对图像产生美感的体验&#xff0c;但是大多数的鬼像都会对图像的质量以…

Python爬虫实战:爬取豆瓣电影

目录 引言 1. 爬虫基础 1.1 什么是爬虫&#xff1f; 1.2 Python爬虫常用库 2. 实战&#xff1a;抓取豆瓣电影Top250 2.1 安装依赖库 2.2 发送HTTP请求 ​编辑 2.3 解析HTML ​编辑 2.4 存储数据 2.5 完整代码 3. 进阶&#xff1a;处理分页和动态内容 3.1 抓取多页…

Redis7——基础篇(六)

前言&#xff1a;此篇文章系本人学习过程中记录下来的笔记&#xff0c;里面难免会有不少欠缺的地方&#xff0c;诚心期待大家多多给予指教。 基础篇&#xff1a; Redis&#xff08;一&#xff09;Redis&#xff08;二&#xff09;Redis&#xff08;三&#xff09;Redis&#x…

Windows 下 Ollama 安装deepseek本地模型

Windows 下 Ollama 安装deepseek本地模型 安装 Ollama 下载 Ollama 下载链接&#xff1a;https://ollama.org.cn/download/windows 下载完成后&#xff0c;按照提示进行安装。 安装过程 安装完成后&#xff0c;安装页面会自动关闭&#xff0c;这是正常现象。 接下来&#…

【鸿蒙开发】第四十三章 Notification Kit(用户通知服务)

目录​​​​​​​ 1 简介 1.1 使用场景 1.2 能力范围 1.3 业务流程 1.4 通知样式 1.5 约束限制 1.6 与相关Kit的关系 2 请求通知授权 2.1 接口说明 2.2 开发步骤 3 管理通知角标 3.1 接口说明 3.2 开发步骤 4 管理通知渠道 4.1 通知渠道类型说明 4.2 接口说明…

bboss v7.3.5来袭!新增异地灾备机制和Kerberos认证机制,助力企业数据安全

ETL & 流批一体化框架 bboss v7.3.5 发布&#xff0c;多源输出插件增加为特定输出插件设置记录过滤功能&#xff1b;Elasticsearch 客户端新增异地双中心灾备机制&#xff0c;提升框架高可用性&#xff1b;Elasticsearch client 和 http 微服务框架增加对 Kerberos 认证支持…

利用非球面透镜进行激光光束重组

这是高斯分布激光束重塑透镜设计的分步演示。该透镜用于将高斯分布转换为成像平面上的均匀照明。 输入激光光束轮廓&#xff1a; 光学结构&#xff1a; Excel 中坐标的数学计算&#xff1a; 输出照度曲线&#xff1a;

(一)趣学设计模式 之 单例模式!

目录 一、啥是单例模式&#xff1f;二、为什么要用单例模式&#xff1f;三、单例模式怎么实现&#xff1f;1. 饿汉式&#xff1a;先下手为强&#xff01; &#x1f608;2. 懒汉式&#xff1a;用的时候再创建&#xff01; &#x1f634;3. 枚举&#xff1a;最简单最安全的单例&a…

nacos编写瀚高数据库插件

1、下载nacos源码 git clone gitgithub.com:alibaba/nacos.git 2、引入瀚高驱动 <dependency><groupId>com.highgo</groupId><artifactId>jdbc</artifactId><version>${highgo.version}</version></dependency> 3、DataSource…

讯飞唤醒+VOSK语音识别+DEEPSEEK大模型+讯飞离线合成实现纯离线大模型智能语音问答。

在信息爆炸的时代&#xff0c;智能语音问答系统正以前所未有的速度融入我们的日常生活。然而&#xff0c;随着数据泄露事件的频发&#xff0c;用户对于隐私保护的需求日益增强。想象一下&#xff0c;一个无需联网、即可响应你所有问题的智能助手——这就是纯离线大模型智能语音…

后端Java Stream数据流的使用=>代替for循环

API讲解 对比 示例代码对比 for循环遍历 package cn.ryanfan.platformback.service.impl;import cn.ryanfan.platformback.entity.Algorithm; import cn.ryanfan.platformback.entity.AlgorithmCategory; import cn.ryanfan.platformback.entity.DTO.AlgorithmInfoDTO; im…

UE 播放视频

一.UI播放视频 1.导入视频文件至工程文件夹 2.文件夹内右健选择Media -> File Meida Source创建testFileMeidaSource文件。 编辑FilePath为当前视频 3.右键->Media->Media Player 创建testMediaPlayer文件 4.右键创建testMediaTexture。编辑MediaPlayer设置testMedia…

推荐一款AI大模型托管平台-OpenWebUI

推荐一款AI大模型托管平台-OpenWebUI 1. OpenWebUI 1. OpenWebUI什么? 官网地址&#xff1a;https://openwebui.com/ GitHub地址&#xff1a; https://github.com/open-webui/open-webui Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台&#xff0c;旨在完全离…

【Python项目】基于知识图谱的百科问答系统

【Python项目】基于知识图谱的百科问答系统 技术简介&#xff1a; 采用Python技术、MySQL数据库、Django框架、Scrapy爬虫等技术实现。 系统简介&#xff1a; 百科问答系统是一个基于知识图谱的问答平台&#xff0c;旨在为用户提供快速、准确的百科知识查询服务。系统通过爬…

stm32rtc实时时钟详解文章

目录 stm32 后备区域基础知识详解 stm32 bkp基础知识详解 Unix时间戳基础知识详解 stm32 rtc实时时钟基础知识详解 相关代码初始化配置 欢迎指正&#xff0c;希望对你&#xff0c;有所帮助&#xff01;&#xff01;&#xff01; stm32 后备区域基础知识详解 stm32芯片的 …

Spring Boot项目@Cacheable注解的使用

Cacheable 是 Spring 框架中用于缓存的注解之一&#xff0c;它可以帮助你轻松地将方法的结果缓存起来&#xff0c;从而提高应用的性能。下面详细介绍如何使用 Cacheable 注解以及相关的配置和注意事项。 1. 基本用法 1.1 添加依赖 首先&#xff0c;确保你的项目中包含了 Spr…

windows上vscode cmake工程搭建

安装vscode插件&#xff1a; 1.按装fastc&#xff08;主要是安装MinGW\mingw64比较方便&#xff09; 2.安装C&#xff0c;cmake&#xff0c;cmake tools插件 3.准备工作完成之后&#xff0c;按F1&#xff0c;选择cmake:Quick Start就可以创建一个cmake工程。 4.设置Cmake: G…

SpringMVC详解

文章目录 1 什么是MVC 1.1 MVC设计思想1.2 Spring MVC 2 SpringMVC快速入门3 SpringMVC处理请求 3.1 请求分类及处理方式 3.1.1 静态请求3.1.2 动态请求 3.2 处理静态请求 3.2.1 处理html文件请求3.2.2 处理图片等请求 3.3 处理动态请求 3.3.1 注解说明3.3.2 示例 3.4 常见问题…