一、一些思考
最近由于想备考中烟的信息岗(考试内容为计算机基础、信息处理、通信技术、电子技术等相关专业知识),由于我是网络空间安全专业,对计网熟悉一点,于是就过了一遍王道咸鱼学长讲的计算机网络,也想借此机会好好归纳整理一下计网的知识点,构建自身对计网的全局掌握,也为后期考高级软考打一点基础。
我目前过完计网的内容,感觉也只是知道各层的协议、算法,以及大致的工作流程,复习的时候我想全局性的复习,而不是简单的记忆每一层的协议,于是在网络上搜索如何复习计网,但搜索的结果几乎都是从头到尾再梳理了一遍。我想我可以设置几个问题,用学习的内容详细的回答数据是如何从最底层的帧封装到最顶层的应用进程的。
网络被发明出来的目的是为了解决两台主机的通信,那么可以设置以下几种情况:
- ①主机与主机直连
- ②主机通过集线器连接(一个/多个集线器的情况)
- ③主机通过交换机连接(一个/多个交换机的情况)
- ④主机通过路由器连接(一个/多个路由器的情况)
- ⑤如果主机是移动站(手机),如何在上述几种类似情况下通信
- ⑥差错控制:分析不同情况下数据丢失或出错的情况(待拆分)
我认为目前学习的内容已经很老,集线器、交换机、路由器已经是被写进教材很多年的通信设备了,当今时代通用的有线/无线通信设备是什么,是怎样运作的,以及WiFi,5G,IPv6,Web3等是如何发展而来的,我觉得是计网学习需要延续的。
下面我会先就上面提出的几种情况进行分析。分析过程尽量回顾所有相关知识。
二、网络分类分析
1.主机与主机直连

1.1 数据传输
主机A 与主机B直接通过网线相连,形成最小的局域网(Local Area Network,LAN)。
LAN:在地理范围较小内(家庭、办公室、学校),由用户自主管理,使用高速通信链路互连的计算机网络。
在这样无法连接互联网的局域网中,也不存在DHCP服务器,就需要手动为主机配置IP地址和子网掩码,保证两台主机在同一个子网中,即子网掩码相同,才能进行通信。(子网掩码用于判断目标IP的本地直连,还是需要交给网关,这是IP协议的工作原理,即使没有网关,也需要这样的判断过程)

现在,假设为两台主机配置好了IP地址,A想要访问B上的Web服务(实质上是请求某个web页面),那么此时A相当于客户端(通过浏览器访问),B相当于服务器(如Apache、Nginx、Python: http.server、自己写的 Socket 程序)。可能的步骤如下:
1. B的Web服务进程启动后,在TCP的80 端口(web服务默认端口)上监听(listen)连接请求
2. A在浏览器中输入B的IP地址(http://192.168.1.4)访问B上的Web服务,生成HTTP请求报文。
超文本传输协议(Hyper Text Transfer Protocol,HTTP):定义了浏览器怎样向服务器请求文档,规定了请求和响应的格式与规则。浏览器通过TCP向服务器发送连接建立的请求,连接建立后就可以发送HTTP请求了。HTTP请求的格式:(待展开)
3. 通过系统调用connect()函数(可能涉及操作系统知识)(此时由OS随机选择一个临时端口号50000,来标识访问web服务的这个进程),从用户态进入为内核态。(应用层--->传输层)
考虑是否补充操作系统内核调用相关知识------待学习
4. 改变TCP状态机(connect()函数的作用),通过三次握手建立TCP连接。(传输层--->网络层--->数据链路层--->物理层--->数据链路层--->网络层--->传输层)
(1) TCP报文段格式:

|------------------------|----------------------------------------------------------------------------------------|
| 源端口与目的端口(16bit=2B) | 传输层与应用层的服务接口,传输层的复用(应用层的多个进程使用不同的端口在传输层使用同一个协议)与分用(一个传输层协议可以通过不同的端口向应用层的多个进程服务)通过端口实现。 |
| 序号(seq,4B) | 标记TCP报文段中第一个字节在原始字节流中的序号。(起始序号由发送方自己设置,序号的作用是便于报文段被分组发送到接收方,接收方可以根据序号进行重组) |
| 确认号(ack,4B) | 表示该序号之前的字节已收到(累计确认)。 |
| 数据偏移(4bit) | 首部长度,表示TCP报文段起始位置到数据部分起始位置的长度。 |
| 保留(6bit) | 全0,留作今后使用。 |
| URG(1bit) | 紧急位,URG=1表示紧急指针有效,可以让紧急数据插队传输。 |
| ACK(1bit) | 确认位,ACK=1表示确认号ack有效。(仅握手1中ACK=0) |
| PSH(1bit) | 推送位,希望接收方尽快将缓存中接收到的数据交付给应用层进程,不需要等缓存填满再向上交付。 |
| RST(1bit) | 复位位,RST=1表示出现严重差错,必须释放TCP连接,或拒绝非法报文段。 |
| SYN(1bit) | 同步位,SYN=1表示连接请求或接受连接的报文段。(仅握手12中SYN=1) |
| FIN(1bit) | 终止位,用于释放连接。FIN=1时表明报文段的发送方数据已经发送完毕,请求释放连接。(挥手12中FIN=1,挥手34中FIN=0) |
| 窗口(rwnd,2B) | 缓存中接收窗口的大小,表示从确认号起还能接收几个字节的数据。 |
| 校验和(2B) | 检验首部和数据部分,计算校验和时加上伪首部。 |
| 紧急指针(2B) | 指向紧急数据的序号。 |
| 选项(长度可变) | 其中规定了最大报文段长度(Maximum Segment Size,MSS),该长度是指TCP报文段的数据部分的最大长度。 |
| 填充(不定) | 调整TCP首部长度为4B的整数倍。 |
PDU:
缓存:为了进行流量控制,接收方与发送方分别都维持一个接受窗口(rwnd)和发送窗口,使用滑动窗口机制来控制传输进度。(接收窗口中的数据向上交付给应用层,其实就是一个char型数组在存储)
校验:同UDP
(2) 三次握手:
①握手1:构造SYN报文段(SYN=1的报文段可称为SYN报文段,ACK同理),SYN报文段:{SYN=1,ACK=0,seq=444,ack=无效,FIN=0}。该报文段不能携带数据,将该报文段封装成IP数据报,交给网络层。
套接字socket={IP地址,端口号}------唯一标识主机中的进程。
服务器端口号------熟知端口号:0~1023; 需要登记使用的端口号:1024~49151
客户端端口号------短暂端口号:49152~65535
②握手2:
5. 连接建立后,调用send()函数将HTTP请求封装成TCP报文段。(或 在建立连接的过程中就调用send()函数,把HTTP请求数据从用户态传入内核态。但在TCP连接建立成功前,HTTP报文存储在缓冲区,连接建立后(TCP状态机显示ESTABLISHED时)才能通过TCP连接封装后传输)
发送HTTP请求
6. B收到HTTP请求后,构造HTTP响应回传给A
HTTP响应
7. 数据传输完毕后,A或B发起TCP四次挥手(注意每次握手和挥手的状态变化),关闭连接
四次挥手
1.2 网络状态
由于主机A与主机B都没有路由功能,所以无法向外接入到互联网。
互联网服务提供商(Internet Service Provider,ISP)通过多台路由器连接到局域网,才能为该局域网提供访问互联网的公网IP地址。局域网的IP地址是私有IP,在全球互联网中不可路由。(这是使用NAT技术的情况)
IP地址发展史:
(1)最初的IP地址(32bit):需要配置IP地址=<网络号,主机号>、默认网关
①单播地址
A类:8bit网络号(0xxxxxxx)+24bit主机号
B类:16bit网络号(10xxxxxxxxxxxxxx)+16bit主机号
C类:24bit网络号(110xxxxxxxxxxxxxxxxxxxxx)+8bit主机号
②多播地址
D类:1110xxxxxxxxxxxxxxxxxxxx
③今后使用
E类:1111xxxxxxxxxxxxxxxxxxxx
(2)子网划分:需要配置IP地址<网络号,子网号,主机号>、默认网关、子网掩码
网络前缀=<网络号,子网号>=(子网掩码)AND(IP地址)
(3)无分类编制CIDR(待展开)
(4)NAT网络地址转换(待展开)
(新问题:现在一般是使用NAT转换公网IP和私有IP,局域网中既然是自主管理,那么可以自己设置IP地址吗?既然我知道哪些是私有IP,哪些是公网IP,那我直接自己随便填一个公网IP可以吗?当然如果乱填的公网IP和别人撞了会不方便使用,我只是对这里IP地址的选择和使用存在疑惑)