强推Linux高性能服务器编程, 真的是后端开发技术提升, 沉淀自身不容错过的一本经典书籍

简介: 强推Linux高性能服务器编程, 真的是后端开发技术提升, 沉淀自身不容错过的一本经典书籍

第1章 TCP/IP协议

1.1 TCP/IP协议族体系结构以及主要协议

TCP/IP协议栈是一个四层协议, 由下而上分别是数据链路层, 网络层, 传输层, 应用层, 上层协议使用下层协议提供的服务.  下三层处在内核态中, 应用层处在用户空间中.

1.1.1 数据链路层

链路层功能: 屏蔽物理层的电气差异, 为上层提供统一服务接口


数据链路层实现了网卡接口的网络驱动程序, 处理数据在不同的物理媒介上的传输


不同的物理网络具有不同的电气特性,网络驱动程序隐藏了这些细节,为上层协议提供一个统一的接口。    下层协议为上层提供统一的接口服务, 隐藏屏蔽掉物理层的不同电气差别.


链路层常用协议: ARP协议 (地址解析协议), RARP协议(逆地址解析协议)


功能: ARP 将IP地址转换为物理MAC地址.    RARP将MAC地址转换为IP地址  

在网络层使用IP地址唯一标识一台主机, 在链路层使用MAC地址唯一标识一台主机

因此网络层必须先将目标机器的IP地址转化成其物理地址,才能使用数据链路层提供的服务

1.1.2 网络层

网络层功能:网络层实现数据包的选路和转发


通常使用众多分级的路由器来连接分散的主机或LAN (局域网), 往往路由器就作为局域网的网关. (借助海关来理解).   每一个路由器都相当于是一个中间结点.


网络层的任务就是选择这些中间节点(路由),以确定两台主机之间的通信路径.


网络层对 上层协议隐藏了网络拓扑连接的细节,使得在传输层和网络应用程序看来,通信的双方是直接相连的。     (为何要分层, 优势出来了, 不同层处理不同的通信细节问题, 分化分工, 使得问题简化, 下层协议为上层协议提供简单易用的接口, 隐藏下层处理的细节问题)


网络层重要协议:IP协议,  ICMP协议  (探路小兵, 主要用来检测连接的)


IP协议根据数据包的目的IP地址来决定如何投递它,如果数据包不能直接发送给目标主机,那么IP协议就为它寻找一个合适的下一跳(next hop)路由器,并将数据包交付给该路由器来转发


数据包是在网络环境中, 一跳一跳的传输. TTL数据包的最长生存时间, 单位也是hop, 跳过TTL还未到达目标主机, 就默认发送失败, 丢弃数据包了, 并且发送ICMP差错报文给源端.

ICMP报文分为差错报文 (回应网络错误) eg: 上述的数据包不可达(3), 重定向(5)


查询报文(ping查询目标是否可达, 网络是否连接)(8),  所以存在类型来区分他们.


ICMP报文还使用8位代码字段来进一步细分不同的条件


比如重定向报文使用代码值0表示对网络重定向,代码值1表示对主机重定向


ICMP报文使用16位校验和字段 对整个报文(包括头部和内容部分)进行循环冗余校验(Cyclic Redundancy Check,CRC),以检验报文在传输过程中是否损坏

1.1.3 传输层

传输层只管端到端的传输, 传输层只关心通信的起始端和目的端,而不在乎数据包的中转过程。

在传输层看来, 两端好似是直接通信的, 实际上中间的中转细节是由网络层处理的   (下层对上层隐藏细节,让上层协议变得尽可能看起来很简单.)

实线箭头表示TCP/IP协议族各层之间的实体通信 (数据包确实是沿着这些线路传递的),而水平的虚线箭头表示逻辑通信线路.


该图中还附带描述了不同物理网络的连接方法。可见,数据链路层(驱动程序)封装了物理网络的电气细节


传输层则为应用程序封装了一条端到端的逻辑通信链路,它负责数据的收发、链路的超时重连等


下层都是在为上层提供服务, 提供便捷, 隐藏细节.


传输层重点协议: TCP, UDP.


TCP是可靠传输协议, 面向连接, 基于流.


可靠来源: 超时重传, 排序号, 确认应答等可靠机制


使用TCP协议通信的双方必须先建立TCP连接, 并在内核中为该连接维持一些必要的数据结构,比如连接的状态、读写缓冲区,以及诸多定时器等.    (超时重传, 确认应答这些机制的实现必然携带着一些内核数据结构. )


当通信结束时,双方必须关闭连接以释放这些内核数据。 ( 连接关闭细节,内核数据结构的释放, 避免内存泄漏 )


UDP协议(User Datagram Protocol,用户数据报协议)则与TCP协议完全相反,它为应用层提供不可靠、无连接和基于数据报的服务


不可靠是因为什么?   因为如果数据在中途丢失,或者目的端通过数据校验发现数据错误而将其丢弃,则UDP协议只是简单地通知应用程序发送失败     (不会重传, 不会确认应答. 所以不可靠)


所以UDP传输的使用往往需要自己处理数据确认、超时重传等逻辑  (自定义UDP可靠传输协议.在应用层书写)


UDP是无连接的, 所以每一次传输数据都需要指定对端的地址 ip + port


基于数据报的服务,是相对基于流的服务而言的。每个UDP数据报都有一个长度,接收端必须以该长度为最小单位将其所有内容一次性读出,否则数据将被截断    


(数据报传输,每次都按照一个包裹传输, 包裹为最小传输单位, 大于包裹数据截断)

1.1.4 应用层

应用层负责处理应用程序的逻辑                                       (用户空间应用程序)


数据链路层、网络层和传输层负责处理网络通信细节       (内核数据结构, 稳定, 安全, 高效)


?为啥不把应用层服务也全部放入到内核态中                  (逻辑众多,会使内核变得非常庞大)


少数服务器程序是在内核中实现的?                                 (省去拷贝的代价, 提高效率,但是代码逻辑复杂, 不便于移植,书写应用)


应用层重点协议,应用程序列举


ping是应用程序,而不是协议,前面说过它利用ICMP报文检测网络连接,是调试网络环境的必备工具

DNS(Domain Name Service,域名服务)协议提供机器域名到IP 地址的转换,我们将在后面简要介绍DNS协议

应用层协议(或程序)可能跳过传输层直接使用网络层提供的服务,比如ping程序


应用层协议(或程序)通常既可以使 用TCP服务,又可以使用UDP服务,比如DNS协议。


我们可以通 过/etc/services文件查看所有知名的应用层协议,以及它们都能使用哪些传输层服务

1.2 封装

前文一直都在说上层协议使用下层协议提供的服务, 但是究竟是如何使用上的呢?  封装


应用程序数据在发送到物理网络上之前, 将沿着内核协议栈从上往下依次传递  (封装, 封包)


每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能, 这个过程就称为封装

每一层都可以进行DDOS攻击.  洪水猛兽.  网络层(可以不断发送连接请求, 或者不断发送fin包.)


DDOS很有意思, 而且暂时没有完全的解决方案, 大致做法就是, 不断地发送无效请求, 占据服务器, 让真正需要使用服务器地人无法建立连接, 或者无法使用.    


解决方法:前面放一台大型地壁垒机器, 过滤无效请求.        (扯多了, 插曲)


经过TCP封装后的数据称为TCP报文段(TCP message segment), 或者简称TCP段。


TCP协议为通信双方维持一个连接,并且在内核中存储相关数据          (内核数据结构:属于内核协议栈)

深入内核协议栈数据结构去看这个封装过程.  


发送地时候是 tcp header + tcp 内核sendbuffer   接收地时候是   tcp header + tcp 内核recvbuffer


send + write数据, 是先写到内核协议栈的传输层的tcp sendbuffer中, 然后经有内核协议栈层层向下封装, 经由网卡接口驱动程序将其放到物理网络传输层 (网线, 电气传输)


经过UDP封装后的数据称为UDP数据报(UDP datagram)。UDP 对应用程序数据的封装与TCP类似。不同的是,UDP无须为应用层数据保存副本,因为它提供的服务是不可靠的.     (不保存副本在内核态意味着不可靠, 不考虑重传的问题)


当一个UDP数据报被成功发送之后,UDP内核缓冲区中的该数据报就被丢弃了。如果应用程序检测到该数据报未能被接收端正确接收,并打算重发这个数据报,则应用程序需要重新从用户空间将该数据报拷贝到UDP内核发送缓冲区中。


经过IP封装后的数据称为IP数据报(IP datagram)


经过数据链路层封装的数据称为帧(frame)。传输媒介不同,帧 的类型也不同

帧才是最终在物理网络上传送的字节序列

1.3 分用

当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将 处理后的帧交给目标应用程序。这个过程称为分用

上层协议那么多, 所以分用的一个核心问题在于如何知道分用后应该交付给哪个上层协议.


掐去头部之后的身子应该交付给谁?


每一层的头部中都会存在这样一个字段可以标识上层协议进行交付


eg : IP协议, ARP协议, RAPR协议都使用帧传输数据,所以帧的头部需要提供某个字段(具体情况取决于帧的类型)来区分它们,帧给出的是帧头部的类型字段进行区分


eg : 以太网帧类型字段的值为0x800,则帧的数据部分为IP数据报


同样,因为ICMP协议、TCP协议和UDP协议都使用IP协议,所以 IP数据报的头部采用16位的协议(protocol)字段来区分它们。


TCP报文段和UDP数据报则通过其头部中的16位的端口号(port number)字段来区分上层应用程序。所有知名应用层协议使用的端口号都可在 /etc/services 文件中找到。


帧通过上述分用步骤后,最终将封装前的原始数据送至目标服务

1.5 ARP协议工作原理

主机向自己所在的网络广播一个ARP请求,该请求包含目标机器 的网络地址。此网络上的其他机器都将收到这个请求,但只有被请求 的目标机器会回应一个ARP应答,其中包含自己的物理地址


核心原理: 广播, 目标MAC ff:ff:ff:ff:ff:ff       同网段的所有主机广播, 对比发现ip等于目标ip的机器,填写自己的MAC物理地址并且发送ack应答包

1.5.1 以太网ARP请求/应答报文详解

硬件地址长度字段和协议地址长度字段,顾名思义,其单位是字节。对MAC地址来说,其长度为6;对IP(v4)地址来说,其长度为 4。


操作字段指出4种操作类型:ARP请求(值为1)、ARP应答(值 为2)、RARP请求(值为3)和RARP应答(值为4)。


最后4个字段指定通信双方的以太网地址和IP地址。发送端填充除目的端以太网地址外的其他3个字段,以构建ARP请求并发送之。接 收端发现该请求的目的端IP地址是自己,就把自己的以太网地址填进 去,然后交换两个目的端地址和两个发送端地址,以构建ARP应答并返回之(当然,如前所述,操作字段需要设置为2)。

1.5.2 ARP高速缓存的查看和修改

通常,ARP维护一个高速缓存,其中包含经常访问(比如网关地址)或最近访问的机器的IP地址到物理地址的映射。这样就避免了重复的ARP请求,提高了发送数据包的速度。


Linux下可以使用arp命令来查看和修改ARP高速缓存。


arp  -a 是查看ARP 缓存内容  

arp  -d  ip   是删除ARP缓存内容

arp  -s  ip  MAC  是添加  ARP缓存内容

1.5.3 使用tcpdump观察ARP通信过程所得结果如下

注意点:


ARP请求和应答是从以太网驱动程序发出的,而并非像图 中描述的那样从ARP模块直接发送到以太网上,所以我们将它们用虚 线表示,这主要是为了体现携带ARP数据的以太网帧和其他以太网帧 (比如携带IP数据报的以太网帧)的区别。


路由器也将接收到以太网帧1,因为该帧是一个广播帧。不 过很显然,路由器并没有回应其中的ARP请求,正如前文讨论的那样


相关文章
|
10天前
|
Java Linux
Springboot 解决linux服务器下获取不到项目Resources下资源
Springboot 解决linux服务器下获取不到项目Resources下资源
|
10天前
|
前端开发 JavaScript 关系型数据库
从前端到后端:构建现代化Web应用的技术探索
在当今互联网时代,Web应用的开发已成为了各行各业不可或缺的一部分。从前端到后端,这篇文章将带你深入探索如何构建现代化的Web应用。我们将介绍多种技术,包括前端开发、后端开发以及各种编程语言(如Java、Python、C、PHP、Go)和数据库,帮助你了解如何利用这些技术构建出高效、安全和可扩展的Web应用。
|
11天前
|
API 数据库 开发者
构建高效可靠的微服务架构:后端开发的新范式
【4月更文挑战第8天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构面临着可扩展性、维护性和敏捷性的挑战。为了解决这些问题,微服务架构应运而生,并迅速成为后端开发领域的一股清流。本文将深入探讨微服务架构的设计原则、实施策略及其带来的优势与挑战,为后端开发者提供一种全新视角,以实现更加灵活、高效和稳定的系统构建。
18 0
|
13天前
|
Linux
linux下搭建tftp服务器教程
在Linux中搭建TFTP服务器,需安装`tftp-server`(如`tftpd-hpa`)。步骤包括:更新软件包列表,安装`tftpd-hpa`,启动并设置开机自启,配置服务器(编辑`/etc/default/tftpd-hpa`),添加选项,然后重启服务。完成后,可用`tftp`命令进行文件传输。例如,从IP`192.168.1.100`下载`file.txt`: ``` tftp 192.168.1.100 <<EOF binary put file.txt quit EOF ```
28 4
|
20天前
|
监控 Java 开发者
构建高效微服务架构:后端开发的新范式
在数字化转型的浪潮中,微服务架构以其灵活性、可扩展性和容错性成为企业技术战略的关键组成部分。本文深入探讨了微服务的核心概念,包括其设计原则、技术栈选择以及与容器化和编排技术的融合。通过实际案例分析,展示了如何利用微服务架构提升系统性能,实现快速迭代部署,并通过服务的解耦来提高整体系统的可靠性。
|
5天前
|
监控 负载均衡 API
构建高性能微服务架构:后端开发的最佳实践
【4月更文挑战第14天】 在当今快速发展的软件开发领域,微服务架构已成为构建可扩展、灵活且容错的系统的首选方法。本文深入探讨了后端开发人员在设计和维护高性能微服务时需要遵循的一系列最佳实践。我们将从服务划分原则、容器化部署、API网关使用、负载均衡、服务监控与故障恢复等方面展开讨论,并结合实际案例分析如何优化微服务性能及可靠性。通过本文的阅读,读者将获得实施高效微服务架构的实用知识与策略。
|
6天前
|
Linux 数据安全/隐私保护
Linux基础与服务器架构综合小实践
【4月更文挑战第9天】Linux基础与服务器架构综合小实践
1192 6
|
7天前
|
小程序 前端开发 JavaScript
小程序全栈开发:前端与后端的完美结合
【4月更文挑战第12天】本文介绍了小程序全栈开发,涵盖前端和后端的关键点。前端使用WXML和WXSS进行页面结构和样式设计,JavaScript处理逻辑及组件使用;后端采用Node.js等语言处理业务逻辑、数据库设计和API接口开发。前端与后端通过数据交互实现结合,采用前后端分离模式,支持跨平台运行。调试测试后,提交微信审核并上线运营。掌握前端后端结合是小程序成功的关键。
|
14天前
|
Linux API C语言
FFmpeg开发笔记(一)搭建Linux系统的开发环境
本文指导初学者如何在Linux上搭建FFmpeg开发环境。首先,由于FFmpeg依赖第三方库,可以免去编译源码的复杂过程,直接安装预编译的FFmpeg动态库。推荐网站<https://github.com/BtbN/FFmpeg-Builds/releases>提供适用于不同系统的FFmpeg包。但在安装前,需确保系统有不低于2.22版本的glibc库。详细步骤包括下载glibc-2.23源码,配置、编译和安装。接着,下载Linux版FFmpeg安装包,解压至/usr/local/ffmpeg,并设置环境变量。最后编写和编译简单的C或C++测试程序验证FFmpeg环境是否正确配置。
35 8
FFmpeg开发笔记(一)搭建Linux系统的开发环境
|
18天前
|
Ubuntu Linux 虚拟化
【Linux】ubuntu安装samba服务器
【Linux】ubuntu安装samba服务器

热门文章

最新文章