上次已经说过,没有协议,不成方圆,计算机之间的通信更是依赖于协议。今天就重点分析一下 TCP 协议。

传输控制协议 TCP 是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络 OSI 模型中,它完成第四层传输层所指定的功能,用户数据包协议(UDP)是同一层内另一个重要的传输协议。

先来复习一下 OSI 的七层模型。

TCP 工作在 OSI 中的第四层——Transport 层,IP 在第三层——Network 层,ARP 在第二层——Data Link 层;在第二层上的数据,我们把它叫 Frame,在第三层上的数据叫 Packet,第四层的数据叫 Segment。 同时,我们需要知道,数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端。

TCP 协议所涉及到的知识太多,没有办法兼顾,我主要想谈谈 3 次握手和 4 次挥手。TCP 的运行可以分为三个阶段,建立连接、传送数据、关闭连接。3 次握手 4 次挥手就对应着建立连接和关闭连接。

操作系统将 TCP 连接抽象为套接字表示的本地端点,作为编程接口给程序使用。在 TCP 连接的生命期内,本地端点要经历一系列的状态改变。我们经常会听到面向 Socket 编程,这是后话了。

要想知道握手是怎样进行了,我们先来看看 TCP 的报文结构。

有以下几点需要说明

TCP 报文中没有 IP 地址,有源端口和目的端口,IP 地址在网络层中的 Packet 中。

Sequence Number(序号),用来标识从 TCP 发送端向 TCP 接收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节在数据流中的序号;通信双方要知道对方的初始化序号,这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP 会用这个序号来拼接数据)。

Acknowledgment Number(确认号)32 位确认序列号包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加 1。不过,只有当标志位中的 ACK 标志(下面介绍)为 1 时该确认序列号的字段才有效。主要用来解决不丢包的问题。

SYN,表示同步序号,用来建立连接。SYN 标志位和 ACK 标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1。

这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有 SYN 的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行 TCP 三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行 TCP 的三次握手。

ACK,TCP 协议规定,只有 ACK=1 时有效,也规定连接建立后所有发送的报文的 ACK 必须为 1 。

FIN,表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送 FIN 标志位的 TCP 数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。

三次握手的过程,即建立一个 TCP 连接的过程,在 Socket 编程中,这一过程由客户端执行 connect 来触发,整个流程如上图所示。

第一次握手:Client 将标志位 SYN 置为1,随机产生一个值 seq=x,并将该数据包发送给 Server,Client 进入 SYN_SENT 状态,等待 Server 确认。

第二次握手:Server 收到数据包后由标志位 SYN=1 知道 Client 请求建立连接,Server 将标志位 SYN 和 ACK 都置为1,ack=x+1,随机产生一个值 seq=y,并将该数据包发送给 Client 以确认连接请求,Server 进入 SYN_RCVD 状态。

第三次握手:Client 收到确认后,检查 ack 是否为 x+1,ACK 是否为1,如果正确则将标志位 ACK 置为1,ack=y+1,并将该数据包发送给 Server,Server 检查 ack 是否为 y+1,ACK 是否为1,如果正确则连接建立成功,Client 和 Server 进入 ESTABLISHED 状态,完成三次握手,随后 Client 与 Server 之间可以开始传输数据了。

注意,不要搞混了 SYN、ACK 只是标志位,seq 是序号,防止乱序,ack 是确认号,主要用来解决不丢包的问题。

四次挥手,即终止 TCP 连接,就是指断开一个 TCP 连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在 Socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发。

由于 TCP 连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个 FIN 来终止这一方向的连接,收到一个 FIN 只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个 TCP 连接上仍然能够发送数据,直到对方也发送了 FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

第一次挥手:主机1(可以使客户端,也可以是服务器端),设置Sequence Number 和 Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;

第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

第三次挥手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机1也可以关闭连接了。

为什么建立连接需要 3 次握手 ?

因为,TCP 协议要保证两端数据的可靠传输,最少就要采取 3 次交互。三次是保证双方互相明确对方能收能发的最低值。下面有个生活中的例子可以感受一下。

TCP之所以使用三次握手,完全是一种为了解决“两军问题”所采用的折衷的设计。所谓“两军问题”,就是红军想告诉蓝军明天下午一起对敌开火,那么红军会派信使 1 号跑过去告诉蓝军,蓝军收到消息再派信使 2 号告诉红军收到,注意,这时蓝军并不知道红军是否收到蓝军的回复。因此需要红军收到回复再派信使 3 号告诉蓝军收到回复,而此时红军也不知道蓝军是否收到回复,因此蓝军收到信使 3 号的消息再派信使 4 号…

还有一个秒懂例子,看到这个真的笑死我了。但是这个例子不严谨哦,权当一乐就好。

三次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,今天balabala……”

两次握手:
“喂,你听得到吗?”
“我听得到呀”
“喂喂,你听得到吗?”
“草,我听得到呀!!!!”
“你TM能不能听到我讲话啊!!喂!”
“……”

四次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,你能听到我吗?”
“……不想跟傻逼说话”

所以说,握手次数要保持刚刚好,2 次不够,4 次多了。

SYN 攻击

SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。

检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。

如何防御 SYN 攻击 ?

SYN 攻击不能完全被阻止,除非将 TCP 协议重新设计。我们所做的是尽可能的减轻 SYN 攻击的危害,常见的防御 SYN 攻击的方法有如下几种:

缩短超时(SYN Timeout)时间

增加最大半连接数

过滤网关防护

SYN cookies 技术

TCP 建立连接为什么要握 3 次手?的更多相关文章

  1. 通俗易懂地讲解TCP建立连接的三次握手和释放连接的四次挥手

    TCP建立连接时,为什么要进行三次挥手? 每一次TCP连接都需要三个阶段:连接建立.数据传送和连接释放.三次握手就发生在连接建立阶段. 在谢希仁著<计算机网络>第四版中讲三次握手的目的是为 ...

  2. TCP建立连接的三次握手过程

    TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是TCP建立连接的全过程. 上图画出了TCP建立连接的过程.假定主机A运行的是TCP客户程序,B运行的是TCP服务器程序.最初两端的TCP进 ...

  3. TCP 建立连接:三次握手

    转自:http://www.cnblogs.com/winner-0715/p/5032661.html 感谢! TCP 建立连接过程 TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是T ...

  4. TCP建立连接三次握手和释放连接四次握手

    TCP建立连接三次握手和释放连接四次握手     [转载]http://blog.csdn.net/guyuealian/article/details/52535294   在谈及TCP建立连接和释 ...

  5. TCP建立连接为什么是三次握手,为什么不是两次或四次?

    什么是三次握手 学过网络编程的人,应该都知道TCP建立连接的三次握手,下面简单描述一下这个过程. 如图所示 第一次握手:客户端发送TCP包,置SYN标志位为1,将初始序号X,保存在包头的序列号(Seq ...

  6. 【转】TCP建立连接三次握手和释放连接四次握手

    在谈及TCP建立连接和释放连接过程,先来简单认识一下TCP报文段首部格式的的几个名词(这里只是简单说明,具体请查看相关教程) 序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数 ...

  7. TCP建立连接的三次握手和TCP连接断开的四次挥手

    1. TCP建立连接的3次握手 2. TCP断开连接的四次挥手 [注意]中断连接端可以是Client端,也可以是Server端. 图3—Client端主动发起关闭连接请求 1. 假设Client端主动 ...

  8. TCP建立连接和释放连接过程

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议.TCP建立连接需要三次握手,释放连接需要四次握手. 1.TCP整 ...

  9. 详解TCP建立连接全过程

    TCP是因特网中的传输层协议,使用三次握手协议建立连接,下面是TCP建立连接的全过程. 上图画出了TCP建立连接的过程.假定主机A是TCP客户端,B是服务端.最初两端的TCP进程都处于CLOSED状态 ...

随机推荐

  1. 51nod1450 闯关游戏

    题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 320 一个游戏App由N个小游戏(关卡)构成,将其标记为0,1,2,..N-1.这些小游戏没有相互制约的性质 ...

  2. ASP.NET 应用生命周期19个事件简介

    下面是请求管道中的19个事件. (1)BeginRequest: 开始处理请求 (2)AuthenticateRequest授权验证请求,获取用户授权信息 (3):PostAuthenticateRe ...

  3. Velocity VelocityEngine 支持多种loader 乱码问题

    最近升级团队的代码生成工具,此工具是velocity实现的. 之前习惯使用UTF-8编码,现在团队使用GBK. 所以遇到一种场景,模板文件使用UTF-8(习惯了所有任性),输出文件使用GBK(项目需要 ...

  4. static_cast、dynamic_cast、reinterpret_cast、和const_c

    ;double dval = 3.14159; ival + dval;//ival被提升为double类型 2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型 int *pi =  ...

  5. [转]编译防火墙——C++的Pimpl惯用法解析

    impl(pointer to implementation, 指向实现的指针)是一种常用的,用来对“类的接口与实现”进行解耦的方法.这个技巧可以避免在头文件中暴露私有细节(见下图1),因此是促进AP ...

  6. [转]STL 容器一些底层机制

    1.vector 容器 vector 的数据安排以及操作方式,与 array 非常相似.两者的唯一区别在于空间的运用的灵活性.array 是静态空间,一旦配置了就不能改变,vector 是动态数组.在 ...

  7. App劫持病毒剖析:你的应用是如何被替换的(病毒防范方法)

    App劫持病毒剖析:你的应用是如何被替换的(病毒防范方法) 一.App劫持病毒介绍 App劫持是指执行流程被重定向,又可分为Activity劫持.安装劫持.流量劫持.函数执行劫持等.本文将对近期利用A ...

  8. Mysql_Learning_Notes_mysql系统结构_2

    Mysql_Learning_Notes_mysql系统结构_2 三层体系结构,启动方式,日志类型及解析方法,mysql 升级 连接层 通信协议处理\线程处理\账号认证(用户名和密码认证)\安全检查等 ...

  9. 【前端vue开发】Hbuilder配置Avalon、AngularJS、Vue指令提示

    偶尔也会研究一下前端内容,因为Hbuilder是基于eclipse开发的,所以用起来倍感亲切啊,而且在我尝试使用的几款前端开发工具中,Hbuilder的表现也是相当出色地,可以访问Huilder官网下 ...

  10. Selenium_多线程执行测试用例

    多线程执行测试用例 这里以百度搜索为例,通过不同的浏览器来启动不同的线程. #!/usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'Yin ...