网络编程套接字( TCP协议通讯流程)

news/2024/6/18 21:11:28 标签: 网络, tcp/ip, 服务器

目录

1、绑定失败问题

2、TCP协议通讯流程

        三次握手的过程

        数据传输的过程

        四次挥手的过程

        TCP和UDP对比


1、绑定失败问题

当我们测试网络代码时,先将服务端绑定8080端口运行,然后运行客户端,并让客户端连接当前服务器

当有客户端连接的情况下,我直接将服务端关闭,此时服务端想要再次绑定8080端口时,就会绑定失败:

综上:如果server在保有连接的时候,server自己先因为一些原因而导致退出,服务器无法立即重启。具体原因等后续博主讲解TCP协议时再详谈。


2、TCP协议通讯流程

下图是基于TCP协议的客户端 / 服务器程序的一般流程:

  • TCP是面向连接的,client 通信前先 connect;server 通信前先 accept
  • TCP在建立连接的时候,采用的是三次握手,在断开连接的时候,采用的是四次挥手 
  • connect发起三次挥手(client),connect只有客户端做。close客户端和服务端都要做。close() client && close() server -> close() 执行4次挥手中的2次

下面我们结合TCP协议的通信流程,来初步认识一下三次握手和四次挥手,以及建立连接和断开连接与各个网络接口之间的对应关系。


三次握手的过程

采用三次握手来建立连接。三次握手的过程就是两台主机建立通信连接的过程。软件服务器架构:客户端(左),服务端(右)

  • 第一次,客户端给服务端发送SYN码,请求连接。
  • 第二次,服务端收到客户端发来的请求,然后表示可以连接,发送SYN+ACK。
  • 第三次,客户端收到服务器的确认,并再次向服务器发送 ACK码表示确认,服务器收到,两台主机建立连接完成。

示例:

  • 偶然的一次机遇,你(客户端)遇到了多年未见的老同学(服务端)。因为变化太大,你只是觉着像,但还是像她微笑点了点头(第一次)。老同学看到了你,一眼就认出了你,也对你微笑点了点头并挥了挥手(第二次)。你看到老同学的反应,更加坚定你们认识。随后,你也向老同学挥了挥手(第三次)。在这个例子中微笑点头用SYN表示,挥挥手用ACK表示。

初始化服务器

  • 服务器完成套接字创建、绑定以及监听的初始化动作之后,就可以调用accept函数阻塞等待客户端发起请求连接了。

服务器初始化:

  • 调用socket,创建文件描述符。
  • 调用bind,将当前的文件描述符和IP/PORT绑定在一起,如果这个端口已经被其他进程占用了,就会bind失败。
  • 调用listen,声明当前这个文件描述符作为一个服务器的文件描述符,为后面的accept做好准备。
  • 调用accept,并阻塞,等待客户端连接到来。

建立连接

  • 而客户端在完成套接字创建后,就会在合适的时候通过connect函数向服务器发起连接请求,而客户端在connect的时候本质是通过某种方式向服务器三次握手,因此connect的作用实际就是触发三次握手。

建立连接的过程:

  • 调用socket,创建文件描述符。
  • 调用connect,向服务器发起连接请求。
  • connect会发出SYN段并阻塞等待服务器应答(第一次)。
  • 服务器收到客户端的SYN,会应答一个SYN-ACK段表示“同意建立连接”(第二次)。
  • 客户端收到SYN-ACK后会从connect返回,同时应答一个ACK段(第三次)。

这个建立连接的过程,通常称为三次握手。

  • 需要注意的是,连接并不是立马建立成功的,由于TCP属于传输层协议,因此在建立连接时双方的操作系统会自主进行三次协商,最后连接才会建立成功。

数据传输的过程

  • 连接一旦建立成功并且被accept获取上来后,此时客户端和服务器就可以进行数据交互了。需要注意的是,连接建立和连接被拿到用户层是两码事,accept函数实际不参与三次握手这个过程,因为三次握手本身就是底层TCP所做的工作。accept要做的只是将底层已经建立好的连接拿到用户层,如果底层没有建立好的连接,那么accept函数就会阻塞住直到有建立好的连接。
  • 而双方在进行数据交互时使用的实际就是read和write,其中write就叫做写数据,read就叫做读数据。write的任务就是把用户数据拷贝到操作系统,而拷贝过去的数据何时发以及发多少,就是由TCP决定的。而read的任务就是把数据从内核读到用户。

数据传输的过程

  • 建立连接后,TCP协议提供全双工的通信服务,所谓全双工的意思是,在同一条连接中,同一时刻,通信双方可以同时写数据,相对的概念叫做半双工,同一条连接在同一时刻,只能由一方来写数据。
  • 服务器从accept返回后立刻调用read,读socket就像读管道一样,如果没有数据到达就阻塞等待。
  • 这时客户端调用write发送请求给服务器服务器收到后从read返回,对客户端的请求进行处理,在此期间客户端调用read阻塞等待服务器端应答。
  • 服务器调用write将处理的结果发回给客户端,再次调用read阻塞等待下一条请求。
  • 客户端收到后从read返回,发送下一条请求,如此循环下去。

四次挥手的过程

四次挥手的过程就是两台主机断开通信连接的过程。软件服务器架构:客户端(左),服务端(右)

  • 第一次,客户端发送FIN给服务端,表达要断开连接,现在是请求断开的状态
  • 第二次,服务端收到FIN请求,回复ACK表达可以,等待结束的状态
  • 第三次,服务端发送FIN给客户端,并且客户端收到ACK请求,进入半连接半断开状态
  • 第四次,客户端收到FIN,等待时间,回复ACK确认,双方进入close状态

示例:

  • 当你成功追到了女孩并走上婚姻的殿堂。结婚后你整体游手好闲,女生受不了你不思进取。便要提出和你离婚(第一次),你同意了她的离婚请求(第二次)。但同意归同意,离婚协议书上你死皮赖脸就是不签字,一直耗着女生。终于有一天,你也无法忍受这样耗下去了,便向她也提出了离婚申请(第三次)。女方果断答应(第四次)。此时双方进入CLOSE状态。

端口连接

  • 当双方通信结束之后,需要通过四次挥手的方案使双方断开连接,当客户端调用close关闭连接后,服务器最终也会关闭对应的连接。而其中一次close就对应两次挥手,因此一对close最终对应的就是四次挥手。

断开连接的过程

  • 如果客户端没有更多的请求了,就调用close关闭连接,客户端会向服务器发送FIN段(第一次)。
  • 此时服务器收到FIN后,会回应一个ACK,同时read会返回0(第二次)。
  • read返回之后,服务器就知道客户端关闭了连接,也调用close关闭连接,这个时候服务器会向客户端发送一个FIN(第三次)。
  • 客户端收到FIN,再返回一个ACK给服务器(第四次)。

这个断开连接的过程,通常称为四次挥手。

注意通讯流程与socket API之间的对应关系

在学习socket API时要注意应用程序和TCP协议是如何交互的:

  • 应用程序调用某个socket函数时TCP协议层完成什么动作,比如调用connect会发出SYN段。
  • 应用程序如何知道TCP协议层的状态变化,比如从某个阻塞的socket函数返回就表明TCP协议收到了某些段,再比如read返回0就表明收到了FIN段。

为什么要断开连接?

  • 建立连接本质上是为了保证通信双方都有专属的连接,这样我们就可以加入很多的传输策略,从而保证数据传输的可靠性。但如果双方通信结束后不断开对应的连接,那么系统的资源就会越来越少。
  • 因为服务器是会收到大量连接的,操作系统必须要对这些连接进行管理,在管理连接时我们需要“先描述再组织”。因此当一个连接建立后,在服务端就会为该连接维护对应的数据结构,并且会将这些连接的数据结构组织起来,此时操作系统对连接的管理就变成了对链表的增删查改。
  • 如果一个连接建立后不断开,那么操作系统就需要一直为其维护对应的数据结构,而维护这个数据结构是需要花费时间和空间的,因此当双方通信结束后就应该将这个连接断开,避免系统资源的浪费,这其实就是TCP比UDP更复杂的原因之一,因为TCP需要对连接进行管理。

TCP和UDP对比

  • 可靠传输 vs 不可靠传输
  • 有连接 vs 无连接
  • 字节流 vs 数据报

http://www.niftyadmin.cn/n/177916.html

相关文章

摸着OpenAI过河,百度文心一言能否“重拳出击”?

“文心一言”对标ChatGPT,饱含争议。文心一言作为一款语言大模型,并提出了自己在技术对就业的影响方面的理解,现阶段正处于摸着OpenAI过河的时候,路该如何走? GPT-4太惊艳,压力给到文心一言 这段时间&…

Android生成签名证书(.keystore)

命令行方式: 首先安装JRE环境,然后使用JRE自带的keytool命令生成签名证书。 keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore -alias是证书别名,建议使用英文字母和数字 -keystore是…

Spring入门之反射机制

Spring相关概念1.1初始Spring在这一节,主要通过以下两个点来了解下Spring:1.1.1Spring家族官网:https://spring.io,从官网我们可以大概了解到:Spring能做什么:用以开发web、微服务以及分布式系统等光这三块就已经占了JavaEE开发的九成多。Spr…

时不我待,拥抱趋势,开源IM项目OpenIM技术简介

坚持开源 开源的理念是基于共享、合作和透明的原则,将软件、代码等知识资源公开并允许他人使用、修改和重新分发,以促进创新和发展。以下是几个开源的优点: 创新:开源可以促进创新,通过让其他人改进或扩展已有的代码…

【思维模型】五分钟了解<金字塔原理>,为什么学习金字塔原理?什么是金字塔原理?如何应用金字塔原理?

【思维模型】五分钟了解<金字塔原理>,为什么学习金字塔原理?什么是金字塔原理?如何应用金字塔原理?1. 为什么学习金字塔原理?2. 什么是金字塔原理?3. 如何应用金字塔原理&#xff1f…

kotlin基础知识复习

kotlin基础知识复习range 范围 从哪里 到哪里Double转Int与类型初始化尽量使用内联函数inlineList和set集合防止空指针和数据获取list去重Mapfield 关键字学习防范竞太条件构造函数运算符重载枚举泛型复习泛型约束中缀表达式重命名了解KT的变换函数KT单例类似java的双重校验效果…

JVM(八)低延迟垃圾收集器

衡量垃圾收集器的三项最重要的指标是:内存占用(Footprint)、吞吐量(Throughput)和延迟(Latency),三者共同构成了一个“不可能三角”。三者总体的表现会随技术进步而越来越好&#xf…

【深度学习】多卡训练__单机多GPU方法详解(torch.nn.DataParallel、torch.distributed)

【深度学习】多卡训练__单机多GPU详解(torch.nn.DataParallel、torch.distributed) 文章目录【深度学习】多卡训练__单机多GPU详解(torch.nn.DataParallel、torch.distributed)1. 介绍2. 单机多GPUの方法2.1 方法1:tor…