网路是怎样连接的(六)TCP的交互(上)
思考重点
- 调用socket后协议栈内部发生什麽事?
- 协议栈是如何看待套接字的?
- TCP如何发起连线?
核心知识
核心知识点
双方沟通的控制消息
协议栈在网路分层中的架构
继上一章介绍了应用程式调用socket的连线流程后,我们将透过协议栈内部的TCP/UDP消息处理来探讨作业系统是如何使用socket消息进行连线以及通讯双方如何使用TCP头部控制消息来互相确认连线状态
我们都知道应用程式会使用socket标识符代表一个本地端与服务端的沟通通道,当使用socket标示符进行操作时,就相当于将本地端与目标服务器的IP与端口号等控制消息交给下层,待操作系统要处理消息时,只要看一下该socket标识符对应的结构体中储存的消息就知道对方的连线资讯
有使用社交聊天软体吗?把socket当成一个聊天视窗,视窗中有双方的沟通讯息,例如姓名、位置、状态等… 其实socket就相当于聊天双方需要的连线消息,也可以说本地端socket就代表一个我跟某某某的聊天室窗,当然有些应用程式可以同时与多个应用程式**“聊天”**
可以把socket想像成代表某一聊天的标示,例如视窗1代表我和小美的对话
netstat指令
我们可以利用windows cmd下的netstat指令来查看本机端的socket内容,毕竟没有实际操作案例其实还蛮难搞懂这种抽象观念,可以透过在cmd中下达netstat -ano得到类似下图的结果
用netstat来查看本地端socket状态
我们看看PID编号为1580的程式的沟通状况,它使用TCP通讯协定,本机IP与端口号为192.168.0.14与8430,且已经和远端服务器完成连线ESTABLISHED,对方服务器IP与端口号分别为52.159.49.199与443
接着来看看PID编号为13348的程式,它使用UDP通讯协定,本机端显示0.0.0.0表示不绑定IP地址,远端服务器地址显示*😗,也是不绑定IP地址的状态,连线状态更是省略掉了,这裡可以清楚看到TCP与UDP的差异
委託TCP进行处理
当应用程式调用socket()创建套接字时,作业系统会为套接字分配一个结构体空间好存放初始化连线消息,等到connect操作时将会把储存沟通消息的结构体做为参数供作业系统连线使用
调用connect()后TCP获得连线双方的位置消息
TCP头部
客户端与服务器进行连线实际上是双方在交换连线控制消息。connect()操作的目的在于使用本地端socket告诉TCP连线资讯,而沟通双方在进行连线操作时是透过更改与查看TCP头部消息来确认每个步骤是否成功,因此接下来我们将大致介绍TCP头部格式
TCP头部主要储存两种消息,(1)客户端与服务器通讯流程需要的控制消息 (2)套接字给的连线消息
TCP头部
本地端口号
长度为16个bits,代表本地端应用程式端口号
目标端口号
长度为16个bits,代表对方服务器应用程式端口号
发送数据的封包序号
长度为32个bits,代表发送数据的封包序号。封包序号的意思是发送方告知接收方该封包的起始位元是占整个封包的第几个bit,要注意起始封包序号不次从1开始,而是在建立连接时乱数产生的。下一次的封包序号就是该次封包序号加上封包的长度(几个bits)
接收数据的封包序号
长度为32个bits,又称为ACK号,它代表接收方告知发送方下一次发送封包要从第几个bits开始
资料偏移
长度为4个bits,它代表TCP内嵌的资料从第几个bytes开始,也可以表示TCP头部消息的总长,使用的单位为4bytes,例如资料偏移位填入6则代表TCP头部总长为6 x 4 = 24 bytes
保留
长度为4个bits,用来当作扩充用,实际应用时必须先设为0
控制位
长度为8个bits,这8个bits分别代表不同的控制消息
比特位 | 涵意 |
---|
CWR | CWR是使用于IP头部ECN的标誌位,用于壅塞视窗控制 | ECE | ECE也是使用于IP头部ECN的标誌位,用来通知网路是否壅塞 | URG | 紧急指标,若URG为1则表示该包资料需要紧急处理 | ACK | 向对方表示接收到消息,除了客户端一开始的连接请求外,都设定成1 | PSH | 是否马上传给上层应用,1表示立刻马上,0表示可以先传递给缓冲区,不用那麽急 | RST | 设为1时代表TCP连线异常,需要强制切断连线 | SYN | 设定为1时用来建立连线,由客户端发起连线操作 | FIN | 通讯结束后若没有数据要传输,将FIN设为1断开连线 |
视窗大小
长度为16个bits,接收方用于告知发送方,无需等待确认可以一次发送的数据大小(后面关于视窗控制时会介绍)
检查码
长度为16个bits,用来检查封包在传递过程中是否发生错误
紧急指标
长度为16个bits,若控制位中的URG设置成1,则表示TCP资料从开头到紧急指标所指向的位置都是需要立刻处理的部分
选项
长度可变,通常用来提升TCP通讯性能,是额外的可选字段
填充
用来补足选项字段的byte数
TCP消息封包
消息封包的传递
上图显示两种不同的封包格式,这裡主要探讨调用socket connect时的封包格式。我们可以把连接阶段的TCP头部看成是一个寻找服务器应用程式的地图。
应用程式透过connect参数将socket储存的消息传递给传输层,TCP模块会对这些消息进行处理并写进头部消息中,在连接初期TCP不会写入资料,所以整个资料封包仅只有头部消息
TCP模块完成对消息的初步封装后便会通知IP模块对该封包进行处理,然后再委託更下层进行封包的封装以及传送
三次握手连线流程
三次握手
一次握手
TCP是面向连接的通讯方式,在进行连接请求前会先准备齐连线所需要的资料。通常连线请求由客户端发出,客户端必须确认服务端的IP地址与端口号,对于TCP头部消息,首先会随机产生一个乱数的发送数据序号,然后把SYN控制位设为1。紧接者客户端发出连接请求,并把状态改为SYN-SEND
二次握手
当接收到客户端的连接请求后,服务器会解析TCP头部并找到等待中的服务器应用程式,并将双方的沟通消息写入服务器上的socket,与此同时服务器产生一个随机的发送数据序列号,并将客户端的发送数据封包序号加上1并且田进自己的接收数据封包序号中,最后将SYN与ACK都设置成1遂返回响应。服务端这时将状态改成SYN-RCVD且该封包一样不含资料区段
三次握手
客户端需要再发送一个封包来完成连线的最后步骤。客户端会将服务器响应的发送数据封包序号加1并填入自己的接收数据封包序号中,同时将ACK设置成1然后发送出去。一旦服务器接收到三次握手的消息,双方将会处于ESTABLISHED状态,也就是我们在netstat视窗中看到的连线状态
|