计算机网络基础概念学习

IT知识
254
0
0
2023-08-28

前言

由于本人知识水平有限,文章内容不可避免的会出现错误和疏漏之处,恳请大家不吝指正!欢迎大家在评论区讨论交流。

计算机网络发展历史

回顾历史,计算机技术早期的发展是缓慢的,甚至是每十年才会迎来一次里程碑式的变革。

时间

计算机工艺

网络

用途

大事件

操作系统

编程语言

20世纪40年代

第一代电子管计算机

-

炮弹弹道轨迹计算

ENIAC问世,进入电脑时代

批处理操作系统

打孔卡

20世纪50年代

第二代晶体管计算机

简单局域网(通信线路+终端)

军用计算

1958年中国第一台计算机诞生

多道程序操作系统

汇编语言和初代高级编程语言(COBOL/FORTRAN)

20世纪60年代

第三代中、小规模集成电路计算机

阿帕网

信息共享

阿帕网成为全球互联网始祖

远程处理、分时、多编程操作系统

更多高级编程语言(PASCAL PL/1、ALGOL-68 )

20世纪70年代

第四代大规模集成电路

ARPNET阿帕网

信息交换

主机对主机协议由NCP向TCP/IP过渡

实时、分时和分布式操作系统

C、C++、DBASE 等编程语言

20世纪80年代

第四代超大规模集成电路

INTERNET因特网

科学教育

全面使用TCP/IP,进入INTERNET时代

实时、分时和分布式操作系统

C、C++、DBASE 等编程语言

20世纪90年代-至今

第四代超大规模集成电路

INTERNET因特网

万物互联

电脑普及,网购兴起

通用网络操作系统

非常多的高级编程语言

操作系统是计算机系统的内核和基石,管理着计算机全部的硬件和软件资源。在使用中渐趋于成熟,先后出现了作业调度管理、处理机管理、存储器管理、外部设备管理、文件系统管理等功能。现代操作系统(如 Windows、Linux 等)本质上来讲都是分时系统,虽然分时系统有进程上下文

切所带来的开销,但却是实现了CPU的最大化利用。

其他事件:有兴趣可以简单了解下

  • 1946年2月15日在美国举行了ENIAC揭幕典礼。这台计算机的问世,标志着电脑时代的开始。
  • 冯·诺依曼发表了计算机史上著名的“101页报告”,报告明确规定出计算机的五大部件(输入系统、输出系统、存储器、运算器、控制器),并用二进制替代十进制运算,大大方便了机器的电路设计,被后人称为“现代计算机之父”
  • 1947年国际标准化组织ISO成立
  • 1956年,国家成立中科院计算技术研究所筹备委员会,在苏联的援助下,中国科研人员得到了M3型计算机的相关资料,1958年中国第一台计算机诞生
  • 1969年末最终建立了由西海岸的4个节点组成的实验性网络,简称ARPANET(阿帕网),四个节点分别是加利福尼亚大学洛杉矶分校,斯坦福研究所,加利福尼亚大学圣巴巴拉分校,犹他大学。阿帕网成为全球互联网的始祖 ,劳伦斯·罗伯茨也就自然成为“阿帕网之父”
  • 1970年完善了最初的主机对主机协议(命名为NCP协议),成为阿帕网使用的标准网络控制协议
  • 1980年,ARPA 投资把 TCP/IP 加进 UNIX BSD4.1 版本的内核中,套接字首先在BSD操作系统中出现,随后几乎渗透到所有主流操作系统中,TCP/IP协议成为操作系统的标准通信模块协议。
  • 1982年中,阿帕网被停用和禁用NCP协议,只允许使用Cern的TCP/IP语言的网站交流。
  • 1983年1月1号,ARPANET将其网络核心协议由NCP替换为更加灵活,功能更加强大的TCP/IP协议。TCP/IP开始成为通用协议,NCP成为历史。这天也被看成是INTERNET时代的开始。
  • 获得美国联邦机构合同的高校开始使用Internet,美国国家科学基金会NSF规划建立了13个国家超级计算中心(根服务器)及国家教育科技网,替代了ARPANET的骨干地位,Internet开始逐渐对外开放!tcp/ip协议栈的民间应用也在此时开始流行,各种基于BSD栈的开源协议栈和商业栈也陆续出现
  • 在中国,国家教育科技网Chinanet、CERnet、CSTnet、Chinagbnet等多个Internet网络项目在全国范围相继启动。Internet开始进入公众生活,并得到了迅速的发展。
  • 1990年ARPANET停止运营,正式退役。Internet开始兴起,各大官方组织开始提供在线服务,Internet开始引起商业界和新闻媒体的注意。
  • 1994 庆祝ARPANET/Internet诞生25周年。
  • 计算机制造技术,操作系统技术也在飞速发展,在连通Internet的计算机中,商业用户逐渐超过了学术界用户,从此Internet成长速度一发不可收拾。
  • 网上冲浪,网商购物成为潮流,走向了千家万户,当今计算机网路更是全方位的涵盖了人们生活中的方方面面,互联网普及率达75.6%,截至2022年12月,我国移动网络的终端连接总数已达35.28亿户,移动物联网连接数达到18.45亿户,万物互联基础不断夯实。

计算机技术是如何被推进的

同很多技术一样,计算机技术的发展离不开国家层面的财政支持和政策指导才得以大力推动

技术发展阶段

发展要素

军工系统计划筹备

有对先进技术和安全的绝对需求

军工系统投入科研

国家有最雄厚的财力,最优秀的人才

军事领域产生并应用

用于国防,提高国家战斗力

教育领域

各大高校和教育组织机构,国家财政补贴,培养对应人才

商用领域

需要考虑成本但可承受的范围比较高

扩散至民用领域

技术特别成熟,成本特别低以后,才能大众化普及

各种“网”的区别

名称

英文名

解释

协议

阿帕网

ARPANET

早期互联网,资源共享

NCP协议

因特网

Internet

现代互联网,资源共享

TCP/IP协议

互联网

internet(小写泛指互联网)

凡是能彼此之间通信的设备组成的网络就叫互联网

所有互联网络都属于互联网

万维网

World Wide Web 环球信息网

现代互联网,超文本资源共享

HTTP协议

net 与 web 的区别

名词

英文名

解释

计算机行业术语理解

net

network

把……织成网

指网络,就是交换机、路由器、光猫、网桥等等构建的互联,由通信线路互相连接的许多自主工作的计算机构成的集合体

web

web page

在…上织网

指网页,由客户端浏览器和无数服务器端构建的,通过网络传输的超文本信息集合体

网络模型

网络是一个复杂的系统,不仅包括大量的应用程序、端系统、通信链路、分组交换机等,这些部件的交互离不开各种各样的协议去规范,而各个部件之间以何种规则进行通信,就是网络模型研究的问题。

网络模型本质是一种协议分层设计方案,分层结构的好处是上层的变动完全不影响下层的结构,每一层都是向它的上一层提供服务,所以网络模型是典型的服务模型。

常见的网络模型有以下三种

网络模型

描述

地位

TCP/IP四层网络模型

应用层,传输层,网络层,网络接口层

实际模型

TCP/IP五层网络模型

应用层,传输层,网络层,数据链路层,物理层

教学模型

OSI七层网络模型

7应用层,6表示层,5会话层,4传输层,3网络层,2数据链路层,1物理层

理论模型

TCP/IP四层网络模型引领了当今互联网的成功,是实际在使用的模型

OSI七层网络参考模型由于出现时间晚,分层太多且不合理,实现复杂,运行效率低等种种原因,并没有得到实际应用,只成为了一个理论模型;而TCP/IP五层网络模型只作为一个教学模型出现在计算机网络教学中,毕竟数据链路层和物理层的问题是需要厂商去考虑的!

TCP/IP这里不单指TCP协议(传输控制协议)IP协议(因特网互联协议),而是对四层模型上的协议共同组成的协议集合的统称,其中TCP协议IP协议是最重要的两个协议,所以就命名为也叫TCP/IP协议簇,我们经常会简称为TCP/IP(网上看到也有叫TCP/IP协议族zu)

TCP/IP四层网络模型的协议和作用

分层名称

协议簇

主要功能

应用层

HTTP、FTP、Telnet、DNS、SMTP等

封装数据、处理数据

传输层

TCP、UDP

传输控制

网络层(网络互联层)

IP协议、ARP协议,ICMP协议,IGMP协议等

网络层编址,寻址和转发

网络接口层

由底层网络定义的协议(有线局域网标准,无线局域网标准)

收发网络上的物理帧

传输控制:逻辑连接的建立、传输层寻址、数据传输、传输连接释放、流量控制、拥塞控制、多路复用和解复用、崩溃恢复等服务

网络协议栈与TCP/IP网络协议栈

网络协议栈则是对网络模型或者说是计算机网络协议套件的具体软件实现,就像类和对象的区别,抽象->实现,马->黑马,网上看到有错误的理解混淆了协议栈与协议簇的概念(协议簇是协议的集合,协议栈是协议簇的实现)

TCP/IP网络协议栈(以下简称TCP/IP协议栈)属于网络协议栈的一种,早在1980年UNIX BSD4版本中就已实现。如今网络通信已经成为操作系统的基础功能,各大操作系统都在内核实现了TCP/IP协议栈(比如Windows和Linux都使用C语言进行了实现),属于操作系统内核栈一部分被默认安装,毕竟谁愿意用不能上网的系统啊!!

网络协议栈本质属于软件开发,所以在不同操作系统的实现、性能、使用都必然会存在一定差异

官方提供的TCP/IP网络协议栈是被操作系统运行在内核的,我们称为内核网络协议栈,除此之外用户网络协议栈(这里的内核和用户说的其实是CPU运行的状态:内核态和用户态),比如 开源TCP/IP协议栈 LwIP,实现的重点是在保持TCP协议主要功能的基础上减少对RAM的占用,除此之外还有一些商业栈用来实现特定需求。

绝大场景的网络编程我们都使用的是官方提供的网络协议栈,如果不是为了某种真实的需求(确实有很多大企业在运行自定义的网络协议栈),真的不要去试图去自己实现。因为最底层都是硬件层面的交互,而用户态是无发直接进行系统调用和操作硬件的,这里有一种“全内核旁路”的概念,即绕过内核,用户态进程直接使用网络硬件,对应的实现技术有DPDK,Netmap等,但这些技术都需要将整个网卡交给一个进程,这是一个巨大的成本,而这个问题操作系统通过CPU调度就能很好解决。

所以对于网络编程,操作系统提供了Socket,去用就好了!通过Socket开发人员就能更简单方便的使用内核网络协议栈进行网络编程了,我们也称这种编程方式为Socket 编程,现在的网络通信基本都是基于socket实现的,这也是为何Socket被称为是通信的基石的原因。

Socket(套接字)

百度词条:Socket 套接字,所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口。

  • 1.是应用程序与网络协议栈进行交互的接口
  • 网络协议栈在内核,应用程序(用户进程)无法直接调用,调用流程为(用户进程执行->调用系统调用->执行系统调用->从系统调用返回)
  • 在此处socket是操作系统提供的应用程序与网络协议栈进行交互的接口,由一组Socket APIs函数组成
  • 2.是应用程序通过网络协议进行通信的接口
  • 根据TCP/IP四层网络模型,应用层之下的三层为传输层,网络层,网络接口层,其上的协议共同组成了TCP/IP协议簇,操作系统将该网络模型实现为了内核网络协议栈
  • 在这个解释下socket是应用程序通过网络协议进行通信的接口
  • 3.从所处的地位来讲,套接字上联应用进程,下联网络协议栈
  • 网络通信时,应用进程调用socket函数,完成与其他三层的服务对接,其他三层的实现是被封装在内核网络协议栈之中的,内核栈由操作系统管理,执行系统调用,而用户进程无法直接执行系统调用,需要通过调用系统调用来进行(流程为用户进程执行->调用系统调用->执行系统调用->从系统调用返回)。
  • 在这个解释下套接字上联应用进程,下联网络协议栈
  • 4.是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象
  • 要进行socket通信,必然会在双方主机上创建进程并打开端口。所谓端点,就是网络端口。是个抽象的概念,并不是物理存在的,在tcp/ip协议中,由一个端口号port表示,在tcp/ip四层模型下,ip+协议+port可以定位一个网络上的进程。
  • 在这个解释下socket就是两个主机应用进程进行双向通信的端点的抽象
  1. 一个套接字就是网络上进程通信的一端
  • socket通信是客户端/服务端模型,存在主动连接的一方(客户端)和对应的被连接的一方(服务端)
  • 在这个解释下一个套接字就是网络上进程通信的一端
  • 6.socket提供了应用层进程利用网络协议交换数据的机制
  • 这里说的是功能了,套接字上联应用进程,下联网络协议栈,网络协议栈是其他三层的协议的实现,而协议是为其上层提供服务的。简单来说就是通过socket,我们无需关注底层的协议实现和通信规则,可以视为通信的双方在应用层实现了进程通信。

所以百度词条的这个解释真的是有点难懂,可以简单理解为

socket是操作系统提供给应用程序使用的一组函数,其内部是对tcp/ip内核网络协议栈的具体实现。
socket通过打开(绑定)一个端口与网络中的另外一个打开(绑定)了socket端口的进程进行通信,这一对socket端口分别称为socket客户端和socket服务端。
socket的出现让网络进程间的通信在应用层即可实现数据交换而不用关注各层网络通信协议本身的实现

应用层协议

使用socket就可以在应用程序中实现不同主机的双间通信,如果只是满足传输简单文本这个要求,socket就够了。但是作为服务端如何理解并正确处理接收到的数据,则需要对通信双方的数据格式,输入输出,错误控制等做出约定。应用层协议的最大意义在于此赋予通信双端的数据以意义

应用层协议分为公开协议和私有协议,公开协议出于公开组织(标准委员会,技术协会),旨在解决抽象的特定场景的通用问题,从而推动网络的发展,比如HTTP协议->超文本传输服务,FTP协议->文件传输服务,SMTP->邮件传输服务,这些公开协议用途广泛,会衍生出很多不同种类的客户端和服务端,就拿http协议来说,其WEB Client客户端应用包括各种浏览器,接口测试工具,抓包工具等,服务器端应用包括各大WEB Server(Apache,Nginx,Tomcat等)

但对部分企业来说(金融,银行等)他们更需要提供安全的服务,所以并不希望协议内容被外界知道,一般都会设计私有应用层协议并闭源其软件源代码,这样你即使抓包都分析不出其TCP数据包的具体意义。

网络编程 socket编程 和 Web编程

广义上的网络编程包括网络各个层面的开发,从操作系统到物理硬件。这个暂不谈论。

我们通常所说的网络编程其实就是socket编程

Web指网页,由客户端浏览器和无数服务器端构建的,通过网络(net+socket)传输的超文本信息集合体,在应用层使用了HTTP协议约定了超文本信息在客户端和服务端在应用层面的通信规则。

Web编程就是指编写基于浏览器/服务器模式的应用程序,使用编程余元分为WEB静态语言和WEB动态语言,WEB静态语言就是通常所见到的超文本标记语言,WEB动态语言主要是ASP,PHP,JAVASCRIPT,JAVA,CGI等计算机脚本语言编写出来的执行灵活的互联网网页程序。

Web编程技术栈最初只有超文本标记语言HTML,属于WEB静态语言,后来逐渐出现了各种WEB动态语言,JAVASCRIPT(运行在浏览器),ASP,PHP,JAVA等进行数据的逻辑处理。

JAVASCRIPT是一种解释性语言,可以与浏览器直接交互,而运行在服务器的动态语言,在与WEB服务端进行交互时,就需要服务端与动态语言的程序通过CGI协议进行内部通信了,用动态语言实现的与WEB服务端交互的程序,我们也成为了CGI程序。

除了CGI程序,如果需要进行数据的存储,则就需要CGI程序通过sql协议和数据库程序通信进行存储,还要各种其他服务中间件,也都是CGI程序通过对应的协议进行访问和操作的。

现如今,web编程的生态是越发的完善,各种前端技术/后端技术/存储和缓存技术层出不穷,共同组成了WEB编程大家庭

在做WEB开发时,我们通常是不需要考虑计算机之间是如何进行网络通信和数据传递的,更侧重于应用层页面的渲染,功能的实现,所以对于网络通信的概念,可以简单理解为数据发送时是由高到低层层封装,接收数据时是由低层到高层层解析即可,底层的网络通信由客户端(浏览器)和 WebServer服务端(nginx/httpd)帮我们实现了,在应用层面双方实现了数据的互通。

一次HTTP请求的过程就是socket通信的一个生命周期。http请求是基于socket实现的。

WebClient 和 WebServer的开发是属于客户端开发领域,

而二次封装而成的 webapi 和 基于cgi的开发则属于web开发,只有低层协议建立后才能进行更高层协议的连接,web编程就是帮我们封装了传输层的TCP协议,而传输层之下的协议连接则是由socket帮我们实现了。

网络结构

网络通信本质上都是客户端/服务器模型,因为都是基于socket的,而socket就是一种双间通信。所以B-S,P-P其实都是一种C-S(客户端-服务端)网络结构,只不过根据其运行特点,使用场景进行了更细的划分

网络结构

特点

B/S

客户端多为浏览器

P/P

每个节点即是客户端,又是服务端

C/S

客户端/服务器模型

TCP连接的生命周期和11种状态

TCP传输控制协议是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议,包含11种状态,TCP连接的11种状态对应了传输过程中的11种可能发生的情况,能够动态地适应错综复杂的互联网(不同的拓扑结构、带宽、延迟、数据包大小和其他参数),从而具备了面对各种故障时的健壮性。

TCP连接的生命周期说白了也是socket完成一次通信的过程,所有的实现都是通过调用socket接口函数,在内核中执行系统调用完成的。在linux上使用最多的socket函数一般有socket()、bind()、listen()、accept()、connect()、close()这几个函数,在window上函数名略有不同,但功能基本一致。TCP连接的生命周期为服务端开启监听->客户端与服务器建立TCP连接->向服务器发送请求报文->服务器返回应答报文->客户端关闭TCP连接

服务端状态

CLOSED->LISTEN->SYN_RECEIVED->ESTABLISHED->正式建立链接,通信->CLOSE_WAIT->LAST_ACK

客户端状态

CLOSED->ESTABLISHED->正式建立链接,通信->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

非常棒的网图 TCP有限状态机

[网络编程大论文] 理论篇

[网络编程大论文] 理论篇

** 网图 Socket工作流程**

[网络编程大论文] 理论篇

** 网图 三次握手**

[网络编程大论文] 理论篇

** 网图 四次挥手**

[网络编程大论文] 理论篇

socket的状态解释

  • CLOSED 没有使用这个套接字[netstat 无法显示closed状态,也就是不存在则不显示,可以理解为一个初始状态或者理论状态]
  • LISTEN 套接字正在监听连接[调用listen后]
  • SYN_SENT 套接字正在试图主动建立连接[发送SYN后还没有收到ACK]
  • SYN_RECEIVED 正在处于连接的初始同步状态[收到对方的SYN,但还没收到自己发过去的SYN的ACK]
  • ESTABLISHED 连接已建立
  • CLOSE_WAIT 远程套接字已经关闭:正在等待关闭这个套接字[被动关闭的一方收到FIN]
  • FIN_WAIT_1 套接字已关闭,正在关闭连接[发送FIN,没有收到ACK也没有收到FIN]
  • CLOSING 套接字已关闭,远程套接字正在关闭,暂时挂起关闭确认[在FIN_WAIT_1状态下收到被动方的FIN]
  • LAST_ACK 远程套接字已关闭,正在等待本地套接字的关闭确认[被动方在CLOSE_WAIT状态下发送FIN]
  • FIN_WAIT_2 套接字已关闭,正在等待远程套接字关闭[在FIN_WAIT_1状态下收到发过去FIN对应的ACK]
  • TIME_WAIT 这个套接字已经关闭,正在等待远程套接字的关闭传送[FIN、ACK、FIN、ACK都完毕,这是主动方的最后一个状态,在过了2MSL时间后变为CLOSED状态]

网络进程间通信原理

网络进程间通信抛开不基于tcp/ip的特殊情况,都是基于客户端/服务器模型网络结构(B-S,P-P其实也是比较特殊的C-S),网络进程间通信只能使用socket进行网络通信。本地进程之间的通信方式也可以采用客户端/服务器模型,使用socket进行通信。但除此之外,本地进程间还有很多种通信方式:管道,消息队列,共享内存,信号量,信号,总共6种通信方式。

使用客户端/服务器模型来进行进程间通信,则必须要用到端口(网络端口),端口号是一个标识符,是TCP/IP协议中一个抽象的概念,由一组整数组成,每个数字代表一个端口号端口号用来定位一个计算机内的进程,IP地址+协议+端口号 可以定位一个网络中的进程(端口)

大家知道tcp/ip协议栈具体实现是用C语言实现的,可能会是以下两种写法(我没去看源码)

unsigned short port = 0;
bool bind(unsigned short port)
{...}

struct tcp{
    unsigned short port;
}

在程序里 端口号是一个变量,也有可能是结构体中的一个成员变量,在数据类型上属于一个无符号的短整型(unsigned short),占2个字节,即16比特,可以标识的最大值为有2^16 -1 =65535,最小值为0,即可以表示65536个值。所以端口号的上限是65536,范围是0-65535,所以理论上同一客户端和同一服务端理论上最多可以建立65535个连接(这个限制是在客户端,服务端一个端口是可以同时建立多个socket连接的)。一般情况下,socket通信时客户端端口号操作系统动态绑定,服务端端口号手动绑定

这也是为啥安装客户端时从不会出现端口占用的问题,而安装服务端程序时有时会出现端口占用问题

参与网络服务的客户端和服务端都需要绑定端口,客户端是不需要监听端口的,服务端需要监听端口。

规则:

网络通信的双方,都必须绑定端口

客户端是不需要监听端口的,服务端需要监听端口

端口与端口号是一对一的,一个端口号代表一个端口

一个端口只能被一个进程监听(新版Linux好像是支持多个了,暂且不论)

一个服务端socket在创建时需要绑定端口号(让客户端知晓,所以不能随机),并开启监听

一个客户端socket只需要绑定端口即可,无需监听

一个进程可以监听多个端口,也可以不监听端口

一个进程可以绑定多个端口,也可以不绑定端口

进程与端口其实并没有什么直接或必然的关系,不过端口必然有进程绑定

网络进程的服务端socket必须需要监听端口

同一主机的进程之间也可以进行网络通信

一个进程可以拥有多个socket连接,一个socket连接就是一对套接字

端口号是操作系统进行抽象,用来定位一个进程

“IP地址+协议+端口”可以标识网络的进程,网络中进程通信即可实现。

Client 端,一个连接会占用一个系统端口

Server 端,所有连接共享同一个端口

网络通讯中,IP地址+端口才能唯一标识一个真实的通讯地址。所有的客户都连接到指定服务端,所以服务端端口号是固定的,而客户端端口号是由操作系统自动分配的。但也可以设定固定的端口范围或者bind固定端口,但可能会产生端口被占用,或者防火墙拦截问题,而且固定客户端的端口号并不能产生任何实际意义。

服务端和客户端是相对的,任何一台设备都可以作为服务端或者客户端。调用connect的主动连接放我们则为客户端;调用bind listen accept 则可监听端口,即可等待连接,我们视这一端的socket为服务端。

逻辑意义上的端口分为三类:公认端口(0-1024),注册端口(1025-49151),动态和/或私有端口(49152-65535),这只是一种协议划分,实际中你大可不必严格遵守,没被占用的端口你都可以使用,当然最好还是用较高的端口号。

其实一个socket连接的一端就是一个端口@!!!

WEB编程网络请求全过程分析

在这一章节主要基于LNMP运行环境进行讨论 ,Linux+Nginx+PHP-FPM(FastCGI)+Mysql,至于Apache(httpd)下的运行模式apache -> httpd -> php5_module -> sapi -> php->mysql,因为本人已弃用,就不做详细描述了。

工作原理

都采用了客户端/服务端模型,使用socket进行通信

httpd是Apache超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程。

而nginx则直接开的是名为nginx的进程

客户端

默认端口号

应用层协议

通信方式

服务端

默认端口号

Client客户端(浏览器)

随机端口

http协议

socket

WebServer服务端(nginx/httpd)

nginx:80

WebServer服务端

nginx:80

cgi/fast-cgi协议

socket

脚本语言解析服务器(fastcgi程序)

php:9000

fastcgi程序

php:9000

mysql协议

socket

Mysql服务器(mysqld)

mysql:3306

fastcgi程序

php:9000

redis协议

socket

Mysql服务器(mysqld)

redis:6379

详细描述

客户端向服务器发送HTTP请求报文的流程

  • 客户端启动
  • 应用层(HTTP协议)
  • 获取原始请求
  • 通过客户端(浏览器)用户输入URL,或用户点击超链接等方式
  • 域名解析
  • 浏览器解析URL,确定请求协议(如HTTP或HTTPS)、域名(Domain)和资源路径
  • 解析域名对应的IP地址
  • 优先进行非权威性解析
  • 检查浏览器缓存中是否存在映射(有过期时间的限制)
  • 检查操作系统缓存中是否存在映射(即本地host文件)
  • 检查本地DNS解析器缓存是否存在映射(cmd:ipconfig/flushdns)
  • 权威性解析
  • 检查本地DNS服务器(填写或分配的首选DNS服务器)是否存在映射
  • 向根DNS服务器(迭代转发)或上一级DNS服务器(递归转发)请求解析
  • 本地DNS服务器在请求完成后缓存映射关系
  • 构造http报文发送http(80端口)请求(由请求方法、请求头、请求正文等构成),如果是https(443端口)还需要提供证书来加密
  • 浏览器与Web服务器建立TCP连接
  • 传输层/网络层/网络接口层的工作由内核实现的TCP/IP协议栈完成,应用层调用scoket函数实现网络通信(可以作为黑盒处理),而在web编程里,对socket的调用也被封装,我们直接使用WEBAPI对外发送HTTP请求,具体的TCP连接建立和socket数据传输的工作由浏览器完成
  • WebServer服务端等待请求
  • 读取请求,解析请求,处理请求,产生数据后,再返回给客户端
  • 如果请求的是静态资源(HTML、CSS、JS、图片等等,不需要查数据库也不需要程序处理),则直接返回给服务器
  • 如果请求的是动态资源,则转发给对应cgi程序处理,并等待处理结果
  • 脚本语言解析服务器(fastcgi程序)-(mysql协议) –> Mysql服务器(mysqld)

Nginx工作原理

推荐文章:www.modb.pro/db/178509 浅谈Nginx的多进程模型

Nginx是多进程模型,多进程解决高并发的设计方案,是应对IO密集型的有效手段之一。所以在开发实践中,遇到类似的场景可以考虑使用类似的解决方案来应对。

  • 启动nginx服务器,初始化master进程,读取nginx.conf配置文件
  • master进程建立好需要监听的端口(默认80)
  • master进程根据配置(看机器CPU情况配置,Worker 进程一般与CPU的核数一致-保持高效的同时不过度占用资源),fork创建出多个worker进程,分配内存,以及其他相关环境初始化。绑定worker进程到指定的cpu内核(多核),每一个worker进程都独享一个CPU,可以在内核中调度
  • 等待请求,服务等待(Listening)
  • 当一个client连接到来时,所有的worker进程都会收到通知,但只有一个可以accept成功。这里Nginx提供了一个共享锁accept_mutex,虽然所有的worker都会收到通知,但只有一个进程抢到锁,其它失败
  • 成功的worker进程接收请求。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。
  • 当运行过程中,如果worker进程出现异常或需要平滑重启时,master会对worker进行重启。重启时会先启动新的worker进程,然后向老的worker发送信号。新的worker启动后,就开始接收新的请求;而老的worker在收到信号后不再接收请求,将当前进程中所有未处理完的请求处理完成后,再退出。这样最大程度的满足可用性要求。

Nginx的动静分离方案?

Nginx的动静分离,原理是将动态请求和静态请求分开,不能单纯的理解成只把动态页面和静态页面物理分离。严格意义上,可以理解成使用nginx处理静态页面,tomcat或PHP处理动态页面。

nginx 怎么和操作系统通信

在nginx当中,信号是操作系统与master进程的通信方式。信号是用来控制master进程的一种手段。包括多钟不同的关闭nginx的方式,更新应用配置文件等

nginx master进程和 worker进程通信方式

通过套接字通信,由Nginx频道实现

ngx_channel_t频道是Nginxmaster进程与 worker进程之间通信的常用工具,使用本机套接字实现的即 socketpair方法,用于创立父子进程间使用的套接字。

worker进程将套接字加入epoll中。这样worker进程在处理http请求时也可以接收到master进程向它发送的消息了。worker进程循环

worker进程间是如何通信的

共享内存是快的通信方式,是worker进程之间的通信方式。需要共享的数据就需要用到共享内存,例如,http连接数,每个worker进程修改的都是共享内存中的数据,该数据是全局变量,对所有的worker进程是共享的。

Nginx和fastcgi通信方式

其实都是socket方式

Socket(套接字)是操作系统定义的一套通信方式和实现通信的系统调用,比如最常用的互

联网上两台终端之间的通信。有时候也代表通信的一端

nginx和fastcgi的通信方式有两种,一种是TCP Socket(网络socket)的方式,一种是Unix Domain Socket(本地socket)方式。

PHP工作原理

工作模式和运行模式说的是什么

运行模式

PHP本身是一个PHP代码的脚本执行程序,运行模式是指其运行的方法。归纳为以下五种方法

  • CGI运行模式(通用网关接口/ Common Gateway Interface)
  • FastCGI运行模式(常驻型CGI / Long-Live CGI)
  • CLI运行模式(命令行运行 / Command Line Interface)
  • Web模块加载运行模式(Apache专属,将php模块安装到apache中,mod_php)
  • ISAPI(Internet Server Application Program Interface)(Windows专属)
  • 以上几种模式中CGI已升级为FastCGI,ISAPI已在php5.3+后的版本中废弃。

所以当下PHP的运行模式其实只有三种:FastCGI,Web模块加载,CLI。

其中FastCGI,Web模块加载这两种运行模式是提供给web服务器来处理php代码文件的。

模块加载的运行模式是最快的,但FastCGI配合nginx WEB服务是目前的主流

PHP在Nginx中运行模式

  • Nginx+PHP-FPM(FastCGI)

PHP-FPM

  • PHP-CGI就是PHP实现的自带的FastCGI管理器,虽然是php官方出品,自带的,但是这丫的却一点也不给力,性能太差,而且也很麻烦不人性化,主要体现在:
  • php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。
  • 直接杀死php-cgi进程,php就不能运行了。
  • 上面2个问题,一直让很多人病垢了很久,所以很多人一直还是在用mode_php,直到 2004年一个叫 Andrei Nigmatulin的屌丝开始发明PHP-FPM ,这神器的出现就彻底打破了这种局面,这是一个PHP专用的fastcgi管理器,它很爽的克服了上面2个问题,而且,还表现在其他方面更表现强劲.
  • 发展历程
  • 从 2004 年开始,我就在等有什么人让 PHP FastCGI 能满足产品环境,但我等不下去了。
  • PHP5.3.3已经集成php-fpm了,不再是第三方的包了。被PHP官方收录了。(PHP 5.3.3发布于2010年7月22日)
  • 从PHP 5.4 RC2开始,php-fpm已经转正了,不再被php团队标注为(实验性的东西)(PHP 5.4发布于2012年3月1日)
  • 此后再加上其他一些因素,也让 Nginx+PHP-FPM(FastCGI) 这种运行模式成为主流。

php-cgi php-fastcgi cgi fastcgi php-fpm之间的关系

  • CGI:(COMMON GATEWAY INTERFACE)公共网关接口,它的作用就是帮助服务器与语言通信,这里就是nginx和php进行通信,因为nginx和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个沟通的协议。
  • FastCGI:是一个与平台无关,与语言无关,任何语言只要按照它的接口来实现,就能实现自己语言的fastcgi能力和web server 通讯。相较CGI,实现了常驻内存,告别了fork-and-execute这种一高并发就宕机的模式
  • CGI与FastCGI都是通用网关接口,是一种外部扩展应用程序与 Web 服务器交互的协议或者说标准公约,CGI可以用任何一种具有标准输入、输出和环境变量的语言(即编程语言)编写,如php、perl、tcl、c、c++, 一般我们说的CGI和FastCGI就是实现了这种标准的程序,我们称之为CGI或CGI程序或CGI服务器,在整个网络请求中php扮演的就是CGI服务器这样的一个角色
  • 在php中我们对实现了CGI标准的这个程序称之为php-cgi,对实现了fastcgi标准的程序称之为php-fastcgi

nginx是如何与php通信的

总结:用户发起请求到nginx上,通过nginx配置文件找到,.php后缀配置fastcgi指定代理端口转发到指的的PHP-FPM进程管理器上,FPM 是一个 PHP 进程管理器,包含 master 进程和 worker 进程两种进程:master 进程只有一个,负责监听端口,主进程php-fpm主要是管理fastcgi子进程,监听9000端口,fastcgi子进程等待请求。当客户端请求到达nginx时,nginx通过location指令,将所有以php为后缀的文件都交给 127.0.0.1:9000 来处理。php-fpm选择并连接到一个fastcgi子进程,并将环境变量和标准输入发送到fastcgi子进程。fastcgi子进程完成处理后将标准输出和错误信息返回。当fastcgi子进程关闭连接时,请求便告处理完成,等待下次处理。

也有直接在nginx中配置中直接选定一个项目对应某个fastcgi进程的配置 属实神奇

应用程序

工作模式

默认运行模式(运行模型)

其他运行模式(废弃或别用)

部署模式

nginx

基于事件驱动的异步非阻塞架构 epoll

多进程+多线程

单进程+多线程

单机/集群

PHP

解释执行

FastCGI(多进程+多线程)

CLI、CGI、模块加载mod_php、ISAPI

单机/集群

Redis

事件循环模型

单线程+单线程串行执行

单线程

单机/集群

mysql

客户端/服务器架构

单进程+多线程模式

单进程+单线程模式

单机/集群

|fastcgi程序|php:9000|redis协议|socket|Mysql服务器(mysqld)|redis:6379|

请详细的分别说一下nginx,php,mysql,redis的工作模式和运行模式

mysql是单进程+多线程模式,所以自身无法平滑重启,需要借助第三方公祖,fork子进程,将服务监听的socket文件描述符传递给子进程,子进程监听父进程的socket,这个时候父进程和子进程都可以接收请求。子进程启动成功之后,父进程停止接收新的连接,等待旧连接处理完成(或超时)。父进程退出,升级完成。这也是大多数软件平滑重启的方案设计(nginx也是如此)

fpm的基本实现

fpm创建master进程,在master进程中创建work pool并监听socket,然后fork出多个子进程(work),这些work在启动后阻塞fcgi_accept_request()上,各自accept请求,有请求到达后worker开始读取请求数据,读取完成后开始处理然后再返回,在这期间是不会接收其它请求的,也就是说fpm的子进程同时只能响应一个请求,只有把这个请求处理完成后才会accept下一个请求。

fpm的master与work进程间不会直接通讯,master通过共享内存获取worker进程的信息,比如worker进程当前状态、已处理请求数等,master要杀死worker进程也是通过发送信号

fpm可以同时监听多个端口,每个端口对应一个worker pool,而每个pool下对应多个worker进程,类似nginx中server概念, 在php-fpm.conf中可以配置多个,例如:

[web1]

listen:127.0.0.1:9000

[web2]

listen:127.0.0.1:9001

php-cgi cgi fastcgi cgi解释器 php-fpm

这些都是与PHP执行有关的概念,它们之间的联系如下:

  1. cgi:是一种通用的协议,用于定义Web服务器和应用程序之间的交互方式。当Web服务器收到请求时,它将请求发送给CGI程序,CGI程序处理请求并生成响应,然后将响应返回给Web服务器,Web服务器再将响应发送给客户端。
  2. php-cgi: 是PHP的一种CGI实现,它可以将PHP代码解释为可执行的二进制文件,并以CGI协议的方式与Web服务器进行通信。
  3. fastcgi:是一种优化的CGI协议,它通过保持与应用程序的长连接来减少CGI程序的启动时间和运行时间,从而提高Web服务器的性能和并发能力。
  4. cgi解释器:是指能够解释CGI程序的应用程序,比如php-cgi就是一种CGI解释器。
  5. php-fpm:是PHP的一种FastCGI实现,它提供了一种高度可定制的、灵活的、高性能的PHP运行环境,并可以与Nginx、Apache等Web服务器配合使用,以提高PHP的性能和并发能力。

概念解析

线程是依附在进程中的,没有进程就没有线程。

一个进程默认提供一条线程,进程可以创建多个线程

进程是一个任务,完成这项任务,需要很多步骤。这些步骤称为线程

单线执行,就是单线程 多线执行就是多线程

现在的基本都是多进程单线程 或者 多进程单线程的,其中就会存在并发问题,如果是单进程单线程的则是串行执行,不会有并发问题。现在有多核cpu,可以实现真正意义上的并发,也就是并行。

除了单进程单线程的运行模型外,其他的运行模型都是为了提高cpu的资源利用率,但是非串行化的执行必然会带来并发问题,这些是我们在高并发编程环境下需要解决的。

根据不同业务场景在串行化和高并发之间做好权衡,使得程序既能保证业务逻辑的正确又能有一定的并发

进程

  • 进程是程序一次动态执行的过程,是程序运行的基本单位
  • 每个进程都有自己的独立内存空间

线程

  • 又叫做轻量级进程,是CPU调度的最小单位。
  • 线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。
  • 多个线程共享所属进程的资源,同时线程也拥有自己的专属资源
  • 单线程就是进程只有一个线程
  • 多线程就是进程有多个线程

多进程单线程模型(好多用这种 nginx redis)

master进程管理worker进程:

  • 接收来自外界的信号
  • 向各worker进程发送信号
  • 监控woker进程的运行状态
  • 当woker进程退出后(异常情况下),会自动重新启动新的woker进程

单进程多线程模型

主线程负责监听客户端的连接请求,workers线程负责处理已经建立好的连接的读写等事件

多进程单线程单进程多线程的目的都是想尽可能的利用CPU,减少CPU的空闲时间,特别是多核环境。

他们在实际运行中,所利用的CPU工作数应该都是相同的。也就是说,你有4核,在某个时刻要么是CPU同时在4个进程做任务(多进程单线程),要么是CPU同时在4个线程上做任务(单进程多线程)。

这是因为,多进程单线程的CPU切换,是从一个进程到另一个进程,而单进程多线程的CPU切换则只在一个进程内,每个进程|线程都有自己的上下文堆栈保存,进程间的切换消耗更大一些。

单进程多线程肯定比多进程单线程快一些,但也快不了多少!!

协程

  • 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。
  • 一个线程可以拥有多个协程,协程不是被操作系统内核所管理,而完全是由程序所控制。
  • 与其让操作系统调度,不如我自己来,这就是协程

并发 (Conurrent)

  • 指的是在同一个时间段内,多条指令在CPU上同时执行(单核CPU的时间片调度)
  • 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。

并行 (Parallel)

  • 指的是在同一时刻,多条指令在CPU上同时执行(多核CPU)
  • 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。

串行

  • 一次只能取得一个任务并执行这个任务,这个任务执行完后面的任务才能继续
  • 你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。

什么是用户态与内核态

  • 用户态、内核态的指令都是 CPU 都在执行,所以我们可以换个说法,实际上这个态代表的是当前 CPU 的状态
  • CPU 指令是做了权限划分的, 例如 Intel X86 中将 CPU 指令权限划分为了 4 个等级
  • Ring0~Ring4 权限由高到低为:Ring0 > Ring1 > Ring2 > Ring3
  • 在 Linux 系统中,由于只有 Ring0 和 Ring3 级别的指令,所以我们可以对用户态、内核态给一个更细节的区别描述:运行 Ring0 级别指令的叫内核态,运行 Ring3 级别指令的叫用户态。
  • 即R0相当于内核态,R3相当于用户态;