网络基础知识(4)——建立与关闭连接

建立 TCP 连接:三次握手  

        前面我们提到过,TCP 协议是一个面向连接的协议,双方在进行网络通信之间,都必须先在双方之间建立一条连接,俗称“握手”,可能在学习网络编程之前,大家或多或少都听过“三次握手”、“四次挥手” 这些词语,那么“三次握手”、“四次挥手”究竟是什么意思,本文将详细讨论一个 TCP 连接是如何建立的,需要经过哪些过程。

        “三次握手”其实是指建立 TCP 连接的一个过程,通信双方建立一个 TCP 连接需要经过“三次握手” 这样一个过程。         

        首先建立连接的过程是由客户端发起,而服务器会时刻监听、等待着客户端的连接,其示意图如下所示:

        TCP 连接一般来说会经历以下过程:

  • 第一次握手

        客户端将 TCP 报文标志位 SYN 置为 1,随机产生一个序号值 seq=J,保存在 TCP 首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入 SYN_SENT 状态,等待服务器端确认。

  • 第二次握手

        服务器端收到数据包后由标志位 SYN=1 知道客户端请求建立连接,服务器端将 TCP 报文标志位 SYN 和 ACK 都置为 1,ack=J+1,随机产生一个序号值 seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入 SYN_RCVD 状态。

  • 第三次握手

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

        注意:上面写的 ack 和 ACK,不是同一个概念:

        小写的 ack 代表的是头部的确认号 Acknowledge number,ack。

        大写的 ACK,则是 TCP 首部的标志位,用于标志的 TCP 包是否对上一个包进行了确认操作,如果确认了,则把 ACK 标志位设置成 1。

        在完成握手后,客户端与服务器就成功建立了连接,同时双方都得到了彼此的窗口大小,序列号等信息,在传输 TCP 报文段的时候,每个 TCP 报文段首部的 SYN 标志都会被置 0,因为它只用于发起连接,同步序号。

        为什么需要三次握手?

        其实 TCP 三次握手过程跟现实生活中的人与人之间的电话交流很类似,譬如 A 打电话给 B:

        A:“喂,你能听到我的声音吗?” 

        B:“我听得到呀,你能听到我的声音吗?”

        A:“我能听到你,………”


        经过三次的互相确认,大家就会认为对方对听的到自己说话,才开始接下来的沟通交流,否则,如果不进行确认,那么你在说话的时候,对方不一定能听到你的声音。所以,TCP 的三次握手是为了保证传输的安全、可靠。

关闭 TCP 连接:四次挥手

        除了“三次握手”,还有“四次挥手”,“四次挥手”(有一些书也会称为四次握手)其实是指关闭 TCP 连接的一个过程,当通信双方需要关闭 TCP 连接时需要经过“四次挥手”这样一个过程。

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

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

        四次挥手过程的示意图如下:

         挥手请求可以是 Client 端,也可以是 Server 端发起的,我们假设是 Client 端发起:

  •  第一次挥手

        Client 端发起挥手请求,向 Server 端发出一个 FIN 报文段主动进行关闭连接,此时报文段的 FIN 标志位被设置为 1。此时,Client 端进入 FIN_WAIT_1 状态,这表示 Client 端没有数据要发送给 Server 端了。

  • 第二次挥手

        Server 端收到了 Client 端发送的 FIN 报文段,向 Client 端返回一个 ACK 报文段,此时报文段的 ACK 标志位被设置为 1。ack 设为 seq 加 1,Client 端进入 FIN_WAIT_2 状态,Server 端告诉 Client 端,我确认并同意你的关闭请求。

  • 第三次挥手

        Server 端向 Client 端发送一个 FIN 报文段请求关闭连接,此时报文段的 FIN 标志位被设置为 1,同时 Client 端进入 LAST_ACK 状态。

  • 第四次挥手

        Client 端收到 Server 端发送的 FIN 报文段后,向 Server 端发送 ACK 报文段(此时报文段的 ACK 标志位被设置为 1),然后 Client 端进入 TIME_WAIT 状态。Server 端收到 Client 端的 ACK 报文段以后,就关闭连接。此时,Client 端等待 2MSL 的时间后依然没有收到回复,则证明 Server 端已正常关闭,那好,Client 端也可以关闭连接了。

        这就是关闭 TCP 连接的四次挥手过程。所以 TCP 协议传输数据的整个过程就如下图所示:

         在正式进行数据传输之前,需要先建立连接,当成功建立 TCP 连接之后,双方就可以进行数据传输了。 当不再需要传输数据时,关闭连接即可!

TCP 状态说明

        TCP 协议在建立连接、断开连接以及数据传输过程中都会呈现出现不同的状态,不同的状态采取的动作也是不同的,需要处理各个状态之间的关系。对于上文中出现的一些状态标志,以及除了这些状态标志之外,其它的一些 TCP 状态,说明如下所示:

  • CLOSED 状态:表示一个初始状态。
  • LISTENING 状态:这是一个非常容易理解的状态,表示服务器端的某个 SOCKET 处于监听状态, 监听客户端的连接请求,可以接受连接了。譬如服务器能够提供某种服务,它会监听客户端 TCP 端口的连接请求,处于 LISTENING 状态,端口是开放的,等待被客户端连接。
  • SYN_SENT 状态(客户端状态):当客户端调用 connect()函数连接时,它首先会发送 SYN 报文给服务器请求建立连接,因此也随即它会进入到了 SYN_SENT 状态,并等待服务器的发送三次握手中的第 2 个报文。SYN_SENT 状态表示客户端已发送 SYN 报文。
  • SYN_REVD 状态(服务端状态):这个状态表示服务器接受到了 SYN 报文,在正常情况下,这个状 态是服务器端的 SOCKET 在建立 TCP 连接时的三次握手过程中的一个中间状态,很短暂,基本上用 netstat 你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。因此这种状态时,当收到客户端的 ACK 报文后,它会进入 到 ESTABLISHED 状态。
  • ESTABLISHED 状态:这个容易理解了,表示连接已经建立了。
  • FIN_WAIT_1 和 FIN_WAIT_2 状态:其实 FIN_WAIT_1 和 FIN_WAIT_2 状态的真正含义都是表示等待对方的 FIN 报文。而这两种状态的区别是:FIN_WAIT_1 状态实际上是当 SOCKET 在 ESTABLISHED 状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 SOCKET 即进入到 FIN_WAIT_1 状态。而当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应 ACK 报文,所以 FIN_WAIT_1 状态一般是比较难见到的,而 FIN_WAIT_2 状态还有时可以用 netstat 看到。
  • TIME_WAIT 状态:表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回 到 CLOSED 可用状态了。如果 FIN_WAIT_1 状态下,收到了对方同时带 FIN 标志和 ACK 标志的报文时,可以直接进入到 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。
  • CLOSE_WAIT 状态:这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方 close 一个 SOCKET 后发送 FIN 报文给自己,你系统毫无疑问地会回应一个 ACK 报文给对方,此时则进入到 CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方, 如果没有的话,那么你也就可以 close 这个 SOCKET,发送 FIN 报文给对方,也即关闭连接。所以你在 CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。
  • LAST_ACK 状态:它是被动关闭一方在发送 FIN 报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到 CLOSED 状态了。

        以上便是关于 TCP 状态的一些描述说明,状态之间的转换关系就如上图中所示。

UDP 协议

        除了 TCP 协议外,还有 UDP 协议,想必大家都听过说,UDP 是 User Datagram Protocol 的简称,中文 名是用户数据报协议,是一种无连接、不可靠的协议,同样它也是工作在传输层。它只是简单地实现从一端 主机到另一端主机的数据传输功能,这些数据通过 IP 层发送,在网络中传输,到达目标主机的顺序是无法 预知的,因此需要应用程序对这些数据进行排序处理,这就带来了很大的不方便,此外,UDP 协议更没有流量控制、拥塞控制等功能,在发送的一端,UDP 只是把上层应用的数据封装到 UDP 报文中,在差错检测 方面,仅仅是对数据进行了简单的校验,然后将其封装到 IP 数据报中发送出去。而在接收端,无论是否收 到数据,它都不会产生一个应答发送给源主机,并且如果接收到数据发送校验错误,那么接收端就会丢弃该 UDP 报文,也不会告诉源主机,这样子传输的数据是无法保障其准确性的,如果想要其准确性,那么就需 要应用程序来保障了。

        UDP 协议的特点:

        ①、无连接、不可靠;

        ②、尽可能提供交付数据服务,出现差错直接丢弃,无反馈;

        ③、面向报文,发送方的 UDP 拿到上层数据直接添加个 UDP 首部,然后进行校验后就递交给 IP 层, 而接收的一方在接收到 UDP 报文后简单进行校验,然后直接去除数据递交给上层应用;

        ④、速度快,因为 UDP 协议没有 TCP 协议的握手、确认、窗口、重传、拥塞控制等机制,UDP 是一个 无状态的传输协议,所以它在传递数据时非常快,即使在网络拥塞的时候 UDP 也不会降低发送的数据。

        UDP 虽然有很多缺点,但也有自己的优点,所以它也有很多的应用场合,因为在如今的网络环境下, UDP 协议传输出现错误的概率是很小的,并且它的实时性是非常好,常用于实时视频的传输,比如直播、 网络电话等,因为即使是出现了数据丢失的情况,导致视频卡帧,这也不是什么大不了的事情,所以,UDP 协议还是会被应用与对传输速度有要求,并且可以容忍出现差错的数据传输中。

端口号的概念

        前面给大家介绍了 IP 地址,互联网中的每一台主机都需要一个唯一的 IP 地址以标识自己的身份,网络中传输的数据包通过 IP 地址找到对应的目标主机;一台主机通常只有一个 IP 地址,但主机上运行的网络进程却通常不止一个,譬如 Windows 电脑上运行着 QQ、微信、钉钉、网页浏览器等,这些进程都需要进行网络连接,它们都可通过网络发送/接收数据,那么这里就有一个问题?主机接收到网络数据之后,如何确定该数据是哪个进程对应的接收数据呢?其实就是通常端口号来确定的。

        端口号本质上就是一个数字编号,用来在一台主机中唯一标识一个能上网(能够进行网络通信)的进程,端口号的取值范围为 0~65535。一台主机通常只有一个 IP 地址,但是可能有多个端口号,每个端口号表示一个能上网的进程。一台拥有 IP 地址的主机可以提供许多服务,比如 Web 服务、FTP 服务、SMTP 服务等,这些服务都是能够进行网络通信的进程,IP 地址只能区分网络中不同的主机,并不能区分主机中的这些进程,显然不能只靠 IP 地址,因此才有了端口号。通过“IP 地址+端口号”来区分主机不同的进程。 很多常见的服务器它都有特定的端口号,具体详情如下表所示:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值