baiyan
全部视频:https://segmentfault.com/a/11...
计算机网络架构的分层与封装
- 我们经常谈到,计算机网络有多种体系架构,如OSI七层模型、TCP/IP四层模型等等。那么,为什么要将计算机网络分成这么多层呢?而且,每一层都要加上其特有的头部(如TCP头部、IP头部等等)进行封装,这样设计的原因又何在?
- 首先我们看一个我们经常看到的C/S架构数据流动过程图:
- 我们以TCP/IP四层网络体系架构为例,总结一下各层服务的作用:
- 应用层:用户直接能够操作的层,处理应用程序的逻辑,在用户空间实现
- 传输层:为两台计算机上的应用程序提供端到端的通信,实现了数据经过网络层到达计算机后能够分发到各个端口(分用),在内核空间实现
- 网络层:提供精确到两端计算机互联网IP地址的通信,实现了数据包在互联网上的选路与转发,在内核空间实现
- 数据链路层:提供基于物理媒介(如网卡)的数据传输服务,在内核空间实现
- 首先谈谈为什么要分层。在我们实际的项目开发过程中,我们常常提到的模块化、服务化,其实和计算机网络为什么要分层的原理类似。我们可以将每一层都看成一个模块、一个服务,其内部的实现细节对于上一层或者下一层都是隐藏的,可能只对外暴露一些API而已。如果上层要使用下层提供的服务,根本不需要关注下一层内部的实现细节,只需使用下层提供的API即可。这样一来,方便了开发与维护,进而提高了计算机网络整体的运作效率。
- 我们再谈为什么要封装。刚才我们谈到了每个模块都是独立的。上层为了使用下层提供的服务,必须封装。举个例子,应用层想使用传输层提供的端到端的数据传输服务,那么传输层就会将应用层下发的数据先存起来。为了实现端到端的数据传输,传输层模块内部需要标识双方的端口号。所以,它就会将端口号还有一些额外的信息(被称作(TCP/UDP)首部),和应用层下发的数据部分进行封装,一起传给下一层(即网络层)。这样,通过封装每一层特有的头部,实现了每一层独特的功能,最终实现了精确到端口号的端到端数据传输服务。
为什么需要FastCGI协议
- 在LNMP架构中,客户端浏览器与nginx代理是通过HTTP协议进行通信的。在请求到达nginx之后,数据最终会被转发给上游的PHP-FPM。它们之间的通信,属于同一机器上、不同端口号之间的通信。FastCGI协议同HTTP协议一样,是基于TCP协议的,处于TCP协议的上层。而 TCP协议传输的仅仅是无意义的字节流数据,接收方并不能正确读取数据的含义。所以,它们也需要一个类似于HTTP的协议的、一种格式或语法上的规范与约定。这样一来,通信双方才能够更好地理解、解析并正确读取对方传输的信息以及数据,理解数据发送方所表达的含义,这就是FastCGI协议开发的目的所在。
抓包
- 接下来我们会以nginx与PHP-FPM之前通信的数据包为例,利用tcpdump抓取二者通信的数据包。所以我们首先需要了解一下各层数据报头部的格式,但是具体每个字段的作用,我们会在接下来详细讲解,先让我们熟悉一下:
数据链路层(以太网帧为例)
网络层(IPv4协议为例)
传输层(TCP协议为例)
各层之间数据包的联系
- 数据链路层是对网络层数据及头部的封装;
- 网路层是对传输层数据及头部的封装;
- 传输层是对应用层数据及头部的封装:
- 由于FastCGI协议基于TCP协议,那么它一定会进行三次握手与四次挥手,中间的数据包是双方的数据交换,全部的数据包如下:
[root@VM_0_3_centos ~]# tcpdump -i lo port 9000 -S -XX
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
13:50:43.883490 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [S], seq 608546013, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 0,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c de3b 4000 4006 5e7e 7f00 0001 7f00 .<.;@.@.^~......
0x0020: 0001 8434 2328 2445 acdd 0000 0000 a002 ...4#($E........
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 3955 ...0..........9U
0x0040: 72e6 0000 0000 0103 0307 r.........
13:50:43.883520 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [S.], seq 2973795481, ack 608546014, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 961901286,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
0x0020: 0001 2328 8434 b140 8499 2445 acde a012 ..#(.4.@..$E....
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 3955 ...0..........9U
0x0040: 72e6 3955 72e6 0103 0307 r.9Ur.....
13:50:43.883541 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [.], ack 2973795482, win 342, options [nop,nop,TS val 961901286 ecr 961901286], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 de3c 4000 4006 5e85 7f00 0001 7f00 .4.<@.@.^.......
0x0020: 0001 8434 2328 2445 acde b140 849a 8010 ...4#($E...@....
0x0030: 0156 fe28 0000 0101 080a 3955 72e6 3955 .V.(......9Ur.9U
0x0040: 72e6 r.
13:50:43.883594 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [P.], seq 608546014:608546982, ack 2973795482, win 342, options [nop,nop,TS val 961901286 ecr 961901286], length 968
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 03fc de3d 4000 4006 5abc 7f00 0001 7f00 ...=@.@.Z.......
0x0020: 0001 8434 2328 2445 acde b140 849a 8018 ...4#($E...@....
0x0030: 0156 01f1 0000 0101 080a 3955 72e6 3955 .V........9Ur.9U
0x0040: 72e6 0101 0001 0008 0000 0001 0000 0000 r...............
0x0050: 0000 0104 0001 03a0 0000 0f35 5343 5249 ...........5SCRI
0x0060: 5054 5f46 494c 454e 414d 452f 6461 7461 PT_FILENAME/data
0x0070: 2f77 7777 2f68 7464 6f63 732f 6461 7461 /www/htdocs/data
0x0080: 2f77 7777 2f68 7464 6f63 732f 736e 6f2f /www/htdocs/sno/
0x0090: 7075 626c 6963 2f69 6e64 6578 2e70 6870 public/index.php
0x00a0: 0c00 5155 4552 595f 5354 5249 4e47 0e03 ..QUERY_STRING..
0x00b0: 5245 5155 4553 545f 4d45 5448 4f44 4745 REQUEST_METHODGE
0x00c0: 540c 0043 4f4e 5445 4e54 5f54 5950 450e T..CONTENT_TYPE.
0x00d0: 0043 4f4e 5445 4e54 5f4c 454e 4754 480b .CONTENT_LENGTH.
0x00e0: 0a53 4352 4950 545f 4e41 4d45 2f69 6e64 .SCRIPT_NAME/ind
0x00f0: 6578 2e70 6870 0b01 5245 5155 4553 545f ex.php..REQUEST_
0x0100: 5552 492f 0c01 444f 4355 4d45 4e54 5f55 URI/..DOCUMENT_U
0x0110: 5249 2f0d 2b44 4f43 554d 454e 545f 524f RI/.+DOCUMENT_RO
0x0120: 4f54 2f64 6174 612f 7777 772f 6874 646f OT/data/www/htdo
0x0130: 6373 2f64 6174 612f 7777 772f 6874 646f cs/data/www/htdo
0x0140: 6373 2f73 6e6f 2f70 7562 6c69 630f 0853 cs/sno/public..S
0x0150: 4552 5645 525f 5052 4f54 4f43 4f4c 4854 ERVER_PROTOCOLHT
0x0160: 5450 2f31 2e31 0e04 5245 5155 4553 545f TP/1.1..REQUEST_
0x0170: 5343 4845 4d45 6874 7470 1107 4741 5445 SCHEMEhttp..GATE
0x0180: 5741 595f 494e 5445 5246 4143 4543 4749 WAY_INTERFACECGI
0x0190: 2f31 2e31 0f0c 5345 5256 4552 5f53 4f46 /1.1..SERVER_SOF
0x01a0: 5457 4152 456e 6769 6e78 2f31 2e31 312e TWAREnginx/1.11.
0x01b0: 390b 0f52 454d 4f54 455f 4144 4452 3131 9..REMOTE_ADDR11
0x01c0: 332e 3232 372e 3234 392e 3132 370b 0552 3.227.249.127..R
0x01d0: 454d 4f54 455f 504f 5254 3533 3931 330b EMOTE_PORT53913.
0x01e0: 0a53 4552 5645 525f 4144 4452 3137 322e .SERVER_ADDR172.
0x01f0: 3136 2e30 2e33 0b02 5345 5256 4552 5f50 16.0.3..SERVER_P
0x0200: 4f52 5438 300b 0d53 4552 5645 525f 4e41 ORT80..SERVER_NA
0x0210: 4d45 6772 6170 652e 7961 662e 636f 6d0f MEgrape.yaf.com.
0x0220: 0352 4544 4952 4543 545f 5354 4154 5553 .REDIRECT_STATUS
0x0230: 3230 3009 0f48 5454 505f 484f 5354 3132 200..HTTP_HOST12
0x0240: 322e 3135 322e 3232 392e 3232 310f 0a48 2.152.229.221..H
0x0250: 5454 505f 434f 4e4e 4543 5449 4f4e 6b65 TTP_CONNECTIONke
0x0260: 6570 2d61 6c69 7665 1209 4854 5450 5f43 ep-alive..HTTP_C
0x0270: 4143 4845 5f43 4f4e 5452 4f4c 6d61 782d ACHE_CONTROLmax-
0x0280: 6167 653d 301e 0148 5454 505f 5550 4752 age=0..HTTP_UPGR
0x0290: 4144 455f 494e 5345 4355 5245 5f52 4551 ADE_INSECURE_REQ
0x02a0: 5545 5354 5331 0f79 4854 5450 5f55 5345 UESTS1.yHTTP_USE
0x02b0: 525f 4147 454e 544d 6f7a 696c 6c61 2f35 R_AGENTMozilla/5
0x02c0: 2e30 2028 4d61 6369 6e74 6f73 683b 2049 .0.(Macintosh;.I
0x02d0: 6e74 656c 204d 6163 204f 5320 5820 3130 ntel.Mac.OS.X.10
0x02e0: 5f31 355f 3029 2041 7070 6c65 5765 624b _15_0).AppleWebK
0x02f0: 6974 2f35 3337 2e33 3620 284b 4854 4d4c it/537.36.(KHTML
0x0300: 2c20 6c69 6b65 2047 6563 6b6f 2920 4368 ,.like.Gecko).Ch
0x0310: 726f 6d65 2f37 352e 302e 3337 3730 2e31 rome/75.0.3770.1
0x0320: 3030 2053 6166 6172 692f 3533 372e 3336 00.Safari/537.36
0x0330: 0b76 4854 5450 5f41 4343 4550 5474 6578 .vHTTP_ACCEPTtex
0x0340: 742f 6874 6d6c 2c61 7070 6c69 6361 7469 t/html,applicati
0x0350: 6f6e 2f78 6874 6d6c 2b78 6d6c 2c61 7070 on/xhtml+xml,app
0x0360: 6c69 6361 7469 6f6e 2f78 6d6c 3b71 3d30 lication/xml;q=0
0x0370: 2e39 2c69 6d61 6765 2f77 6562 702c 696d .9,image/webp,im
0x0380: 6167 652f 6170 6e67 2c2a 2f2a 3b71 3d30 age/apng,*/*;q=0
0x0390: 2e38 2c61 7070 6c69 6361 7469 6f6e 2f73 .8,application/s
0x03a0: 6967 6e65 642d 6578 6368 616e 6765 3b76 igned-exchange;v
0x03b0: 3d62 3314 0d48 5454 505f 4143 4345 5054 =b3..HTTP_ACCEPT
0x03c0: 5f45 4e43 4f44 494e 4767 7a69 702c 2064 _ENCODINGgzip,.d
0x03d0: 6566 6c61 7465 140e 4854 5450 5f41 4343 eflate..HTTP_ACC
0x03e0: 4550 545f 4c41 4e47 5541 4745 7a68 2d43 EPT_LANGUAGEzh-C
0x03f0: 4e2c 7a68 3b71 3d30 2e39 0104 0001 0000 N,zh;q=0.9......
0x0400: 0000 0105 0001 0000 0000 ..........
13:50:43.883602 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [.], ack 608546982, win 357, options [nop,nop,TS val 961901286 ecr 961901286], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 f67c 4000 4006 4645 7f00 0001 7f00 .4.|@.@.FE......
0x0020: 0001 2328 8434 b140 849a 2445 b0a6 8010 ..#(.4.@..$E....
0x0030: 0165 fe28 0000 0101 080a 3955 72e6 3955 .e.(......9Ur.9U
0x0040: 72e6 r.
13:50:43.885366 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [P.], seq 2973795482:2973795650, ack 608546982, win 357, options [nop,nop,TS val 961901288 ecr 961901286], length 168
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 00dc f67d 4000 4006 459c 7f00 0001 7f00 ...}@.@.E.......
0x0020: 0001 2328 8434 b140 849a 2445 b0a6 8018 ..#(.4.@..$E....
0x0030: 0165 fed0 0000 0101 080a 3955 72e8 3955 .e........9Ur.9U
0x0040: 72e6 0106 0001 008d 0300 582d 506f 7765 r.........X-Powe
0x0050: 7265 642d 4279 3a20 5048 502f 372e 322e red-By:.PHP/7.2.
0x0060: 3132 0d0a 436f 6e74 656e 742d 5479 7065 12..Content-Type
0x0070: 3a61 7070 6c69 6361 7469 6f6e 2f6a 736f :application/jso
0x0080: 6e3b 2063 6861 7273 6574 3d75 7466 2d38 n;.charset=utf-8
0x0090: 0d0a 0d0a 7b22 7374 6174 7573 223a 3531 ....{"status":51
0x00a0: 342c 226d 7367 223a 2255 6e65 7863 6570 4,"msg":"Unexcep
0x00b0: 7465 6420 6120 656d 7074 7920 636f 6e74 ted.a.empty.cont
0x00c0: 726f 6c6c 6572 206e 616d 6522 2c22 6461 roller.name","da
0x00d0: 7461 223a 5b5d 7d00 0000 0103 0001 0008 ta":[]}.........
0x00e0: 0000 0000 0000 0077 5c2f .......w\/
13:50:43.885378 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [.], ack 2973795650, win 350, options [nop,nop,TS val 961901288 ecr 961901288], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 de3e 4000 4006 5e83 7f00 0001 7f00 .4.>@.@.^.......
0x0020: 0001 8434 2328 2445 b0a6 b140 8542 8010 ...4#($E...@.B..
0x0030: 015e fe28 0000 0101 080a 3955 72e8 3955 .^.(......9Ur.9U
0x0040: 72e8 r.
13:50:43.885396 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [F.], seq 2973795650, ack 608546982, win 357, options [nop,nop,TS val 961901288 ecr 961901288], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 f67e 4000 4006 4643 7f00 0001 7f00 .4.~@.@.FC......
0x0020: 0001 2328 8434 b140 8542 2445 b0a6 8011 ..#(.4.@.B$E....
0x0030: 0165 fe28 0000 0101 080a 3955 72e8 3955 .e.(......9Ur.9U
0x0040: 72e8 r.
13:50:43.885667 IP VM_0_3_centos.33844 > VM_0_3_centos.cslistener: Flags [F.], seq 608546982, ack 2973795651, win 350, options [nop,nop,TS val 961901288 ecr 961901288], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 de3f 4000 4006 5e82 7f00 0001 7f00 .4.?@.@.^.......
0x0020: 0001 8434 2328 2445 b0a6 b140 8543 8011 ...4#($E...@.C..
0x0030: 015e fe28 0000 0101 080a 3955 72e8 3955 .^.(......9Ur.9U
0x0040: 72e8 r.
13:50:43.885678 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [.], ack 608546983, win 357, options [nop,nop,TS val 961901288 ecr 961901288], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 0034 f67f 4000 4006 4642 7f00 0001 7f00 .4..@.@.FB......
0x0020: 0001 2328 8434 b140 8543 2445 b0a7 8010 ..#(.4.@.C$E....
0x0030: 0165 fe28 0000 0101 080a 3955 72e8 3955 .e.(......9Ur.9U
0x0040: 72e8 r.
- 我们可以看到,前三个包就是TCP的三次握手,经过了一定量的数据传输之后,最后四个包就是TCP的四次挥手,我们可以用下图来进行表示:
- 我们挑选第二个数据包进行详细讲解。我们可以分析出,它是建立TCP连接的三次握手中的第二次握手,是由服务端返回给客户端的ACK包:
13:50:43.883520 IP VM_0_3_centos.cslistener > VM_0_3_centos.33844: Flags [S.], seq 2973795481, ack 608546014, win 43690, options [mss 65495,sackOK,TS val 961901286 ecr 961901286,nop,wscale 7], length 0
0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
0x0020: 0001 2328 8434 b140 8499 2445 acde a012 ..#(.4.@..$E....
0x0030: aaaa fe30 0000 0204 ffd7 0402 080a 3955 ...0..........9U
0x0040: 72e6 3955 72e6 0103 0307 r.9Ur.....
- 每一组是4个16进制数字,所以每一组是16位,即两个字节。
- 由于当前数据包是经过层层封装的最终的数据包,所以它包含帧头部、IP头部、TCP头部、以及应用程序数据(参考上图)下面我们逐个字节分析:
帧头部
- 0000 0000 0000:源MAC地址(源MAC地址是6个字节,由于都是本机所以为全0)
- 0000 0000 0000:目的MAC地址(目的MAC地址是6个字节)
- 0800:表示类型为IP数据报(类型字段为了区分是使用IP协议、ARP协议还是RARP协议类型的帧)
IPv4协议头部
- 4:版本号为IPv4
- 5:IP协议头部长度为5 * 4(以4B为单位计算) = 20字节
- 00:8位服务类型
- 003c:总长度为60字节
- 0000:16位标识(同一个IP数据报的所有分片的标识均相同)
- 4000:3位标志 + 13位片偏移(0100 0000 0000 0000)(010代表禁止分片,片偏移为0)
- 40:8位生存时间TTL(数据报到达目的地之前允许的路由器跳数,通常为64)
- 06:8位协议(用来区分上层协议,6为TCP)
- 3cba:16位头部校验和(接收端使用CRC算法检验IP数据报头部是否损坏)
- 7f00 0001:32位源端IP地址(转化为十进制127.0.0.1)
- 7f00 0001:32位目的端IP地址(转化为十进制127.0.0.1)
TCP协议头部
- 2328:16位源端口号(十进制值为9000,因为PHP-FPM的端口号为9000)
- 8434:16位目的端口号(十进制值为33844,是建立初始TCP连接时产生的随机端口号)
- b140 8499:32位序号(十进制值为2973795481,是服务端的初始序号)
- 2445 acde:32位确认号(十进制值为608546014,代表客户端608546013及之前序号的报文段已全部收到)
- a:TCP协议头部长度为10 * 4(以4B为单位计算) = 40字节
- 012:6位保留 + URG|ACK|PSH|RST|SYN|FIN (012 = 000000 010010,即ACK = 1及SYN = 1,符合三次握手规律)
- aaaa:16位窗口大小(十进制值为43690,告诉对方自己的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制数据的发送速度)
- fe30:16位校验和(接收端使用CRC算法检验TCP数据报头部及数据部分是否损坏,是TCP可靠传输的保障)
- 0000:16位紧急指针(用来让发送端给接收端发送紧急数据)
- 0204 ffd7 0402 080a 3955 72e6 3955 72e6 0103 0307:20字节的TCP头部选项
- 当三次握手之后,TCP连接正式建立。我们可以在下面几个包中看到具体的HTTP协议的请求行、请求主体、以及相应的返回状态码及响应主体等内容。
- 我们总结一下,FastCGI协议其实就相当于基于TCP协议的HTTP协议。在LNMP架构中,nginx是一个web服务器,只支持HTTP协议数据的输入与输出;而PHP-FPM只支持FastCGI协议的输入与输出,这里nginx就可以看成是一个协议转换器的作用。它下层的TCP协议是面向字节流传输的,传给对方的只是一堆的字节数据,接收方无法解析其内容所代表的含义。那么我们开发HTTP协议、FastCGI协议等等也是同理。为了能够让PHP-FPM更加轻松容易地解析nginx转发过来的数据包,读懂基于TCP的这些字节流数据的含义,那么我们必须约定一种数据格式,让数据的传输、读取更加方便、高效、规范,这就是开发FastCGI协议的目的。这篇文章只是给大家一个复习以及铺垫,具体FastCGI协议所规定的格式与详细内容请听下回分解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。