1.OSI模型
OSI(open systems interconnection)计算机通信开放系统互连模型,是一个七层的理论模型(也就是说理论上分得很细致完善,但实际中设计实现中有出入)
实际过程中我们一般采用网际网协议族
物理层和数据链路层干的事情可以对应为网络硬件和设备驱动程序,如果不是要写驱动程序,一般我们不予关心。
网络层中规定的协议是什么呢? 就是我们经常说的IPV4和IPV6,
传输层中规定的协议是什么呢?TCP/UDP/SCTP,编写网络程序的人主要就是关注这一块
理论中的会话层/表示层/应用层实际中合并成一层,统称应用层,一些网络应用,包括常见的web浏览器 qq 网易云音乐都是这一层的产物
我们需要牢牢记住上面的层次结构
2.传输层
TCP(传输控制协议)
TCP是一个滑动窗口协议,即一个TCP连接的发送端在某个时刻能发多少数据是由滑动窗口控制的,而滑动窗口的大小实际上是由两个窗口共同决定的,一个是接收端的通告窗口,这个窗口值在TCP协议头部信息中有,会随着数据的ACK包发送给发送端,这个值表示的是在接收端的TCP协议缓存中还有多少剩余空间,发送端必须保证发送的数据不超过这个剩余空间以免造成缓冲区溢出,这个窗口是接收端用来进行流量限制的,在传输过程中,通告窗口大小与接收端的进程取出数据的快慢有关。另一个窗口是发送端的拥塞窗口(Congestion window),由发送端维护这个值,在协议头部信息中没有,滑动窗口的大小的就是通告窗口和拥塞窗口较小值,所以拥塞窗口也看做是发送端用来进行流量控制的窗口。滑动窗口的左边沿向右移动称为窗口合拢,发生在发送的数据被确认时(此时,表明数据已被接收端收到,不会再被需要重传,可以从发送端的发送缓存中清除了),滑动窗口的右边沿向右移动称为窗口张开,发生在接收进程从接收端协议缓存中取出数据时。随着发送端不断收到的被发送数据的ACK包,根据ACK包中的确认序号和通告窗口大小使滑动窗口得以不断的合拢和张开,形成滑动窗口的向前滑动。如果接收进程一直不取数据,则会出现0窗口现象,即滑动窗口左边沿与右边沿重合,此时窗口大小为0,就无法再发送数据。
下面附一个TCP协议头的格式和滑动窗口的示意图(截自TCPIP协议详解):
图1.TCP头部结构
图2.滑动窗口示意图
6.TCP连接是全双工的
意味着在一个给定的连接上应用可以在任何时刻在进出两个方向上既可以发送数据又接收数据。相当于通道被一分为二变成两个子通道,通道数据流方向相反,对于每个子通道TCP都要跟踪诸如序列号和通告窗口大小等状态信息。通过某些手段,可以转换成一个单工连接。
7.TCP是一个字节流(byte-stream),消息无边界,要自行定义规则
TCP连接的建立和终止(重点来了)
牢牢记住上面的这张图
三路握手过程:(建立)(需要三个分节)
- 服务器先调用socket创建套接字,调用bind绑定端口,调用listen监听端口(从此句可以看出为什么之前我们运行时间获取客户端程序的时候,需要先确保服务器程序已经运行),调用accept
- 客户端调用 socket创建客户端套接字,选定一个端口后(一般系统自行选择,也可以认为选择),主动发起连接请求(调用connect),导致客户TCP发送一个SYN(同步)分节给服务器,它告诉服务器客户将在(待建立的)连接中发送的数据的初始序列号。通常SYN分节不携带数据,所在IP数据报只还有一个IP首部,一个TCP首部和可能的TCP选项(记住这个东西,以后很有用)
- 服务器必须确认(ACK)客户的SYN,自己也得发送一个SYN(其中也包含服务器将在同一分节中发送的数据初始化序列号),服务器将上述作为一个整体分节发送给客户端
- 客户端ACK服务器的SYN
再看上述图时,要注意三路握手的具体过程分别发生在函数调用的什么时期,三路握手起始于客户connect的主动调用,当connect成功返回时,完成了前两路,并开始第三路,而服务器端在接收到ACK后,会阻塞到read(现在只需要有大致印象,以后详解)
TCP连接终止:(通常需要4个分节)
特别说明
- ACK M+1 和FIN N过程之间可能还有数据的流动(半关闭)(也就是被动关闭进程确认了别人的FIN,发送ACK后,但自己还没有调用close关闭自己的套接字的这段时间)
- 应用进程调用close主动关闭套接字会使得所在端TCP发送一个FIN。Unix进程调用exit或从main返回,或收到一个终止进程信号,所有打开的描述符都会被关闭(套接字可看成一种特殊的描述符),使得仍然打开的TCP连接上也会发送一个FIN
TCP状态转换图
参见我另一篇博文 tcp状态转换详解
UDP(用户数据报协议)
暂略,持续更新~~