计算机网络_TCP的三次握手

IP协议

IP协议是 无连接 的通信协议, 作用在网络层 *主要作用是:负责寻址和路由选择,即将网络地址翻译为物理地址然后确定如何将数据从发送方路由到接收方.

它不会占用两台正在通信的计算机之间的通信线路, 这样IP协议就降低了对网络线路的需求,每条线可以同时满足许多不同计算机之间的通信需要.

通过IP协议,消息或者其他要传送的数据会被分割为较小的独立的包然后在网络中传送,这种被分割成的包叫做数据包.

IP协议 只负责将每个包路由至它的目的地,但是IP协议没有做任何事情来确认数据包是否按顺序发送或者包是否被破坏,这个需要它的上层传输层中的协议来解决.

传输层控制协议TCP

  1. 面向连接的,可靠的,全双工的(两边都可以发送也可以接收),基于字节流的传输层通信协议.
  2. 将应用层的数据流分割成报文段并发送网络层. 注意:应用层以上数据单位都是报文,数据链路层是数据帧,网络层是数据包,物理层是比特流
  3. TCP协议为了保证不丢失包,每个数据包都有序号(seq Sequence Number),对方收到则发送ACK确认,如果发送端在合理的往返时延TCP_TIMEOUT_INIT内未收到确认则重传.
  4. TCP协议用一个奇偶校验和函数来检验数据在传输过程中是否有误.

TCP报文头
如图:
在这里插入图片描述
TCP Flags

  • URG: 紧急指针标志,为1表示紧急指针有效,为0则忽略紧急指针.
  • ACK:确认序号标志,为1表示这是一个用于确认的报文.
  • PSH: push标志.
  • RST: 重置连接标志.
  • SYN:同步序号标志,用于建立连接过程,为1表示这是一个请求建立连接的报文.
  • FIN:结束标志,用于释放连接,为1时表示发送方已经没有数据发送了,关闭连接.

TCP的三次握手
握手是为了建立连接,TCP三次握手流程图如下:
在这里插入图片描述

  1. 刚开始客户端和服务器端都会处于关闭状态,当双方打开之后,服务端便立刻进入LISTEN即监听状态.
  2. 客户端首次向服务器端发送请求报文,此时同步序号标志SYN为1,而序号seq为任意正整数值x,向服务器端发送完报文后,客户端便进入了名为SYN_SENT(同步_已发送)的状态.在此时之前发送的那个报文段被称为SYN报文段,这个报文不能携带数据,但是会消耗一个序号,这就是第一次握手!!!
  3. 当服务器接收到请求报文以后,先确认客户端发来的请求报文, 如果同意连接,则向客户端发出确认报文,确认报文中的SYN同步标志位为1,ACK确认标志位为1,序列号为y(任意正整数), 确认号ack为x+1(客户端传过来的序列号+1).给客户端发送确认报文之后,服务器便进入了SYN_RCVD(同步_已接收)阶段,这个报文也不能携带数据,但是仍然会消耗一个序列号,这就是 第二次握手.
  4. 当客户端接收到确认报文之后,先检查服务器端发来的确认报文,然后向服务器发出一个确认报文,其中ACK确认序号标志为1,seq序号为x+1,ack确认号为y+1(服务器发给我的序号是y,我作为回应要还给你,但是又消耗了一个序号,所以+1),这个报文 是可以携带数据,会消耗一个序列号,不携带数据就不消耗序号 这就是 第三次握手.
  5. 客户端将确认报文发送给服务器端之后,客户端就进入了ESTABLISHED已建立连接的状态.
  6. 服务器端收到确认报文后,服务器端便也随之进去了ESTABLISHED已建立连接的状态,此时可以发送数据了.

总结
在这里插入图片描述
小知识:

  • TCP和UDP数据包中都是不包含ip信息的,因为ip是网络层的事情,而他俩在传输层.
  • TCP和UDP数据包中都会有源端口目的端口,也就是说,端口是在传输层的.
  • 两个进程在同一台计算机内部进行通信,可以被PID(进程号)来唯一标识某个进程,但是这个只在本地唯一.
  • 如果把两个进程放在了不同的计算机,那么如果要进行通信的话,PID是不能唯一定位到两个进程的,解决方法就是使用在传输层中的端口号来唯一标识某个进程
  • IP地址+端口号+协议号(标识上层是TCP还是UDP)可以唯一标识某一台主机的某个进程.

为什么需要三次握手才能建立起连接?

  1. 为了初始化Sequence Number的初始值,让双方知道对应的seq,也就是上面的x和y,这个序列号是以后进行通信的序号,来保证应用层接收到的数据不会因为网络等问题而乱序,之后TCP会用这个序号来拼接数据,所以会有第三次握手,客户端通知服务器端已经收到服务器端的seq的初始化值.

  2. 如果只有两次握手,那么服务器端收到了客户端传来的SYN=1的请求连接数据包之后,便会分配资源并向客户端发送ACK=1的确认连接数据包

    这样会产生一个问题: 当客户端与服务器端正常建立连接,发送数据结束关闭TCP连接之后,如果在之前客户端与服务器端建立连接过程中残留的数据包此时才到达服务器端,那么服务器端就会认为客户端又申请了一次连接,然后又给客户端分配资源发送确认连接报文,但是此时是没有数据会发送给服务器端的,服务器就只能一直等着,知道超时,这就造成了服务器端资源的浪费.

首次握手会有一个隐患:—>SYN超时问题

SYN超时问题是指: 如果服务器端收到了客户端SYN,向客户端回复SYN-ACK报文之后客户端发生了掉线了之类的情况,导致服务器端未收到客户端发送的ACK确认的情况.

当服务器端没有收到客户端的ACK确认报文前,此时暂时双方就处于一个中间状态,没有成功也没有失败,一定时间后如果服务器端还没有收到客户端发来的ACK报文后,服务器端就会不断重试(即重发SYN-ACK报文至客户端)直至超时,linux下默认重试次数为5次,重试的间隔时间从1秒开始,每次都翻倍,比如:1s->2s->4s->8s->16s,第五次发出去之后,再等待32s,还没收到就判定位超时,断开连接(即63s后TCP断开连接).

这样子可能会使得服务器遭受SYN Flood攻击,即恶意程序给服务器发一个SYN报文之后就不发ACK报文了,服务器每次都会等待一段时间才断开连接,次数太多了,会使得SYN半连接队列(server收到SYN请求连接报文后将client放到半连接队列)耗尽,会导致其他正常的请求无法处理.

SYN Flood攻击解决办法(有好几个,我只写一个嘿嘿嘿):
其一就是: 当server收到client的SYN之后,不立即分配资源,而是根据client发送过来的SYN计算出一个cookie值,这个cookie值用来 存储server返回给client的SYN+ACK数据包中的初始序列号seq,当client发送第三次握手的ACK包之后进行校验,如果校验成功则server分配资源,建立连接.那么当syn半连接队列满了之后没有进行校验的请求就会被抛弃.

如果已经建立连接,客户端出现故障怎么办?

TCP有保活机制: 也就是说,TCP设有保活计时器,服务器每收到一次客户端的请求后都会重新复位这个计时器,时间一般是俩小时,如果俩小时服务器端还没收到客户端的任何数据,即连接处于非活动状态,则服务器端会向客户端发送探测报文,如果未收到响应,会每隔75秒钟发送一个,若连续发送10个仍然没反应,服务器端就会断开连接.

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值