合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
[TOC] ## 前言 ### 说在前面 **把**他叫做笔记,就是因为这些内容是我在阅读了各种书籍,论坛以及博客之后自己整理的,所以,不是百分百原创但是又可以说是百分百原创。所以特此声明一下。 **整**理这篇笔记我用了好几天的时间,虽然自己知道很多内容,但真的要一点一点整理出来还是挺麻烦的,因为要把和Swoole相关的知识单独拎出来,说简单也很简单,说难其实也挺难。 其实搞Swoole的话,我感觉最基本的就是TCP,UDP了。之前我把OSI七层的全写了,但是感觉太乱了,这么多层,知识点本来就杂乱,而且任意一层都会有不同的技术细节,都整理出来,GET不到重点,所以这里我们就从IP/TCP/UPD/HTTP开始。 >ps:作为一个初级phper,下面的内容了解即可,如果想深入学习网络编程,我推荐几本书,这几本书都是我看过并且经常翻阅的,都写的很好,作为一个程序员想计算机知识自上而下不说精通,光完全理解都谈何容易,所以个人感觉最好有个侧重点比较好,所以书籍我也只是推荐,毕竟我自己走了不少弯路,曾经年幼无知的我连cpu上电时序图都看,然而现在我只是个phper,curdboy~ >初级入门的话我推荐《图解HTTP》 然后我看了《一本书读懂TCP/IP》 下面的书是我平时当作字典遇到问题查的 《UNIX网络编程 卷1:套接字联网API》 《UNIX网络编程 卷2:进程间通信》 《TCP&IP网络编程》 ## 正文 **首先贴一个TCP/IP协议栈的图,下面的知识参照这个图来理解。** :-: ![](https://img.kancloud.cn/ed/80/ed80130010957e7dd938e97b8bd40783_654x339.png) ### IP地址(网络层) IP地址众所周知,Windows系统查询网络IP地址为ipconfig,Linux中为ifconfig或者ip addr命令。Windows如下图所示。 :-: ![](https://img.kancloud.cn/2d/2c/2d2cf824955aab1d59c8c4be54e69e7f_595x289.png) :-: **ipconfig效果图** IPv4的IP地址是32个字节的,如百度的115.239.210.27就是一个IP地址,它的作用是一个网卡的地址,具有定位作用。现在想一想MAC地址是一个网卡出厂就具备的全球唯一的地址,那么有了MAC地址后,怎么还需要IP地址了?答案就是没有IP地址根本定位不了,给你一个百度的服务器MAC地址,你怎么能找到他了。MAC地址就像我们的身份证,IP地址就如同我们的家庭住址+名字。比如给你小王的MAC地址,你也不可能找到他,只有先通过他的家庭住址和名字,才能找到他。**所以说MAC地址不具备大范围的定位作用,只有在局域网内才有作用**,这就是MAC地址和IP地址的一个区别。 32位的IP地址被分成了一下五类,又大大的减少了IP地址数量。A、B、C是有网络号和主机号组成的。这样是为了区别是不是在同一个局域网内,网络号代表的是小区,主机号代表的是哪一号房间。这样不同的小区就可以都有1001号房间了,但不会产生冲突,因为他们的网络号不同。 :-: ![](https://img.kancloud.cn/26/39/2639b7ee25a10dc2d0cbb27c4d91f509_1090x458.png) :-: **IP地址分类图** 如下图所示,A、B、C三类的最大主机数量,很容易产生浪费。私密地址代表什么了,我们上学的时候IP都是172.16开头的,貌似很多大学的IP都是一样的,你会问这不是产生冲突了吗,只能说,这些IP在局域网里面是正常使用的,一段到了公网后,这个就会被替换成一个不冲突的IP了,数据请求返回时,再被替换回来,这样就保证了不冲突,详情下面会说,现在有个概念就可以了。 :-: ![](https://img.kancloud.cn/5b/a6/5ba6a973479040775d562a9abe51c41c_1200x340.png) **怎么判断是否是同一个局域网的IP地址了?** 通过配置的子网掩码。如下图是一个C类的私有IP地址,网络号为24位,主机号位8位,广播地址为192.168.1.255,一般默认的网关为192.168.1.1.将子网掩码和IP地址按位与计算后,就可以得到网络号了,也就可以判断目标IP是否是要出网关了。 D类地址是组播地址,也就是说这个组的网卡都会收到改组的数据。 此外还介绍一个特殊的IP地址,127.0.0.1。他是个环回接口,这个地址用于本机通信,经过内核处理后直接返回给本机。 :-: ![](https://img.kancloud.cn/16/26/1626f415269690db08729ea342518e21_414x430.png) :-: **IPv4相关配置** Linux中配置IP地址如下: ~~~cpp sudo ifconfig eth1 192.168.1.174/24 //给eth1这个网卡配置IP和子网掩码 sudo ifconfig eth1 up // 启动 ~~~ **简单的数据发送过程:**系统会判断数据包的目标IP是不是在同一个网段中,如果是是同一个网段,他会通过ARP协议广播获取目标IP的MAC地址,直接发送给目标即可。如果是跨网段,那么获取网关的MAC地址,把数据发给网关就不管了。 >关于IP协议我就不写了,如果后续有时间了,我争取整理一份网络编程的笔记,但应该会是很久之后了。 ### TCP(传输层) TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内 另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。 应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元( MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体 的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。 #### 三次握手 TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK ,并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。 TCP三次握手的过程如下: * 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN\_SEND状态。 * 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN\_RECV状态。 * 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。 #### 连接成功 连接成功之后双方即可互相传输字节流,并随时可关闭连接,传输的数据有以下特性 * 传输的数据被tcp分割成了最适合发送的数据块 传递给ip协议,这个发送数据称为 报文段 或 段 * tcp作为可靠性连接,每次发送数据段,会启动一个定时器,每次接收数据段,会发送一次确认,如果定时器没有及时收到确认,则会重发数据 * TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)。 * 两个应用程序通过TCP连接交换8bit字节构成的字节流。TCP不在字节流中插入记录标识符。我们将这称为字节流服务(bytestreamservice)。如果一方的应用程序先传10字节,又传20字节,再传50字节,连接的另一方将无法了解发方每次发送了多少字节。只要自己的接收缓存没有塞满,TCP 接收方将有多少就收多少。一端将字节流放到TCP连接上,同样的字节流将出现在TCP连接的另一端。 #### 四次挥手 建立一个连接需要三次握手,而终止一个连接要经过四次挥手,这是由TCP的半关闭(half-close)造成的。具体过程如下所示。 * 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。 * 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。 * 注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。 * 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。 * 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。 既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。 > “通常”是指,某些情况下,步骤1的FIN随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。 在步骤2与步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这称为“半关闭”(half-close)。 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。 无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。 #### php中的tcp php可通过socket函数,swoole扩展,stream流函数进行创建tcp协议的socket,绑定网卡端口,进行tcp服务端/客户端操作 在php中,我们并不需要了解tcp的握手/挥手,我们只需要知道ip:port能连接/创建 一个tcp服务端/客户端就行了 使用php的socket,我们可以直接发送字符串,接收的也是字符串,其他一切都是语言,操作系统所需要做的事, 我们只需要处理好字符串的完整性,例如我们使用php做tcp服务端 * 客户端连接成功后,发送了一个"abcabcabcabc"的字符串 * 而服务端每次只接收9个字节,那第一次获取只会接收到"abcabcabc"的残缺字符串,需要继续获取数据 ### HTTP 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hypertext),这成为了HTTP超文本传输协议标准架构的发展根基。Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。 #### 技术架构 HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。(我们称这个客户端)叫用户代理(user agent)。应答的服务器上存储着(一些)资源,比如HTML文件和图像。(我们称)这个应答服务器为源服务器(origin server)。在用户代理和源服务器中间可能存在 多个中间层,比如代理,网关,或者隧道(tunnels)。尽管TCP/IP协议是互联网上最流行的应用,HTTP协议并没有规定必须使用它和(基于)它支持的层。 事实上,HTTP可以在任何其他互联网协议上,或者在其他网络上实现。HTTP只假定(其下层协议提供)可靠的传输,任何能够提供这种保证的协议都可以被其使用。 通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端发送过来的请求。一旦收到请求,服务器(向客户端)发回一个状态行,比如"HTTP/1.1 200 OK",和(响应的)消息,消息的消息体可能是请求的文件、错误消息、或者其它一些信息。 HTTP使用TCP而不是UDP的原因在于(打开)一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正。 通过HTTP或者HTTPS协议请求的资源由统一资源标示符(Uniform Resource Identifiers)(或者,更准确一些,URLs)来标识。 :-: ![](https://img.kancloud.cn/65/ec/65ec16abdeba733f8be8afbd41e8ac9d_396x300.png) #### 过程解析 http一次请求的过程大概如下: * 用户在浏览器输入www.baidu.com * dns服务器解析/或者本机hosts,路由器hosts对比 获得ip * 浏览器访问默认端口80,则访问的tcp地址为 ip:80 * tcp协议3次握手,建立连接 * 发送一个http request请求头 * 服务器获得http request请求头,表明该次访问为http访问,解析http请求头,获得请求类型,请求格式,以及请求数据(cookie,get,post数据) * 服务器发送response响应数据,主动断开 * 浏览器接收response响应数据,解析响应文本类型,解析数据,断开连接 > https协议中,在请求以及响应时多了一层tls,ssl加密解密协议,默认端口从80变为了443 ### WebSocket