草庐IT

【Linux-计算机网络】-TCP协议通信流程

13KB 2023-05-25 原文

1.TCP协议通信流程图

 

1.1TCP协议的通讯流程可以分为以下步骤:

  1. 应用层:应用程序通过系统调用API(如socket)创建一个TCP套接字(socket),并设置好相关的选项。

  2. 传输层:当应用程序调用connect函数建立TCP连接时,TCP协议开始进行三次握手协议:

    a. 客户端向服务端发送SYN数据包(SYN_SENT状态);

    b. 服务端收到SYN数据包后,向客户端发送SYN+ACK数据包(SYN_RCVD状态);

    c. 客户端收到SYN+ACK数据包后,向服务端发送ACK数据包(ESTABLISHED状态)。

  3. 网络层:TCP数据包被封装在IP数据包中,经过网络层进行路由选择和传输。

  4. 数据链路层:TCP/IP数据包被封装在以太网帧中,通过数据链路层进行物理传输。

  5. 传输层:当数据到达目的地后,TCP协议会进行四次挥手协议

    a. 客户端向服务端发送FIN数据包(FIN_WAIT_1状态);

    b. 服务端收到FIN数据包后,向客户端发送ACK数据包(CLOSE_WAIT状态);

    c. 当服务端完成数据发送后,向客户端发送FIN数据包(LAST_ACK状态);

    d. 客户端收到FIN数据包后,向服务端发送ACK数据包,此时连接关闭(CLOSED状态)。

  • TCP在建立连接的时候,采用的是三次握手,在断开连接的时候,采用的是四次挥手 。

这里的重点是三次握手和四次挥手,接下来我们重点讲解一下。

 1.2三次握手过程

 👿Linux三次握手是指TCP连接建立的过程中,客户端和服务端之间通过交换三个数据包来确认彼此的身份和建立连接的过程。

  1. 第一次握手:客户端发送SYN(同步)数据包给服务端,请求建立连接。(SYN数据包包含客户端的初始序列号(seq number),用于同步客户端和服务端的数据传输。)

  2. 第二次握手:服务端收到SYN数据包后,发送一个SYN-ACK(同步-确认)数据包给客户端。(SYN-ACK数据包包含服务端的初始序列号和对客户端SYN数据包的确认。)这个阶段,服务端已经准备好了接收来自客户端的数据。

  3. 第三次握手:户端收到SYN-ACK数据包后,发送一个ACK(确认)数据包给服务端。(ACK数据包包含客户端对服务端SYN-ACK数据包的确认,以及客户端的初始序列号。)此时,客户端和服务端都已经准备好了通信,可以开始传输数据。此时,客户端和服务端之间的TCP连接已经建立完成

就比如你跟你同学说周末到他家里玩(SYN)希望他能够同意。你同学知道了你要到他家玩(收到SYN)表示你那天啥时候来都行(SYN-ACK)让你知道他同意了。

当你知道了同学同意你去他家后,你就要为周末去他家做准备(发送ACK)。

🌈服务器的初始化 

当服务器完成套接字的创建绑定和监听后,可以调用accept函数阻塞等待客户端发起连接请求。

服务端初始化的过程:

  1. 创建套接字:使用socket()函数创建一个套接字,该套接字可以用于接受客户端连接请求。

  2. 绑定端口:使用bind()函数将套接字绑定到一个具体的端口上,以便客户端可以通过这个端口来连接服务器。

  3. 监听连接:使用listen()函数将套接字设置为监听状态,以便接受客户端的连接请求。

  4. 接受连接:使用accept()函数等待客户端的连接请求,当客户端发起连接请求时,accept()函数会返回一个新的套接字描述符,用于和客户端进行通信。

  5. 处理请求:使用新的套接字描述符和客户端进行通信,处理客户端发送过来的请求,并发送响应给客户端。

  6. 关闭连接:当客户端请求处理完成后,关闭套接字描述符,释放相应的资源。

  • 需要注意的是,在服务端处理请求的过程中,可能会有多个客户端同时发起连接请求,因此需要使用多线程或多进程的方式来处理这些请求。同时,服务端也需要进行异常处理,防止因为网络问题或其他原因导致服务器异常退出。

接下来就是客户端与服务器的交流了。

C/S建立连接过程 

客户端与服务器建立连接的过程如下:

  1. 客户端创建一个套接字:使用socket()函数创建一个套接字,用于与服务器进行通信。

  2. 设置连接参数:使用connect()函数将套接字连接到服务器的地址和端口上。

  3. 发起连接请求:使用connect()函数发起连接请求,向服务器发送一个SYN数据包,表示客户端请求连接。

  4. 等待服务器响应:客户端会等待服务器的响应,如果服务器接受了连接请求,就会发送一个SYN+ACK数据包回来,表示服务器愿意建立连接。

  5. 确认服务器响应:客户端接收到服务器的SYN+ACK数据包后,会发送一个ACK数据包,表示客户端确认连接请求已经成功建立。

  6. 建立连接:当服务器接收到客户端发送的ACK数据包后,连接就正式建立了,客户端和服务器可以开始进行通信。

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

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

 

数据传输的过程 

 

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

示例:

  1. 客户端使用send()函数将数据发送给服务器。发送的数据可以是任何格式的数据,例如字符串、二进制数据等。

  2. 服务器使用recv()函数接收客户端发送的数据。在接收数据之前,服务器需要先使用accept()函数接受客户端的连接请求,获取到一个新的套接字描述符。服务器从这个新的套接字描述符中读取客户端发送的数据。

  3. 服务器使用send()函数将响应数据发送给客户端。响应数据可以是任何格式的数据,例如字符串、二进制数据等。

  4. 客户端使用recv()函数接收服务器发送的响应数据。

  5. 客户端和服务器之间进行多次数据的传输,直到完成数据的传输任务。

 四次挥手的过程

四次挥手的过程就是两台主机断开通信连接的过程。

TCP连接的四次挥手过程如下:

  1. 客户端发送一个FIN报文,表示客户端已经没有数据要发送给服务器了,并要求服务器关闭连接。客户端进入FIN_WAIT_1状态

  2. 服务器接收到客户端发送的FIN报文后,向客户端发送一个ACK报文作为响应。此时,服务器进入CLOSE_WAIT状态,等待应用程序关闭连接

  3. 如果服务器有尚未发送的数据,会在数据发送完毕后再发送一个FIN报文给客户端,表示服务器已经没有数据要发送了。服务器进入LAST_ACK状态

  4. 客户端接收到服务器发送的FIN报文后,向服务器发送一个ACK报文作为响应。此时,客户端进入TIME_WAIT状态,等待一段时间后才关闭连接。服务器接收到客户端发送的ACK报文后,进入CLOSED状态,连接关闭。

端口连接

  • 当双方通信结束之后,需要通过四次挥手的方案使双方断开连接,当客户端调用close关闭连接后,服务器最终也会关闭对应的连接。而其中一次close就对应两次挥手,因此一对close最终对应的就是四次挥手。
  • 其中最后一次挥手是为了确保数据传输的完整性和可靠性,避免数据重复和丢失等问题。在断开连接之前,需要确保所有的数据都已经被传输完毕,并且各个状态和缓存已经被正确处理和释放,避免可能的资源泄露和数据损失。

需要注意的是,客户端进入TIME_WAIT状态的目的是为了确保服务器接收到客户端发送的ACK报文,避免可能的数据重传和延迟。在客户端等待的这段时间内,客户端不会再向服务器发送任何数据,同时等待的时间也是由TCP协议栈决定的,通常为2倍的最大段生存时间

👿四次挥手的好处 

  1. TCP四次挥手的主要作用是安全地关闭连接并释放资源。在TCP连接中,一旦完成了数据的传输,就需要关闭连接以释放占用的资源,避免资源浪费和不必要的等待。
  2. 四次挥手的过程可以保证数据传输的完整性和可靠性,避免出现数据丢失和错误。同时,四次挥手的过程也可以保护连接的安全性,避免数据被未经授权的用户访问和篡改。
  3. 另外,四次挥手过程中,服务器可以先关闭连接并等待客户端的确认,避免出现客户端长时间占用连接资源的情况。这样可以有效地避免连接的滥用和资源的浪费。
  4. 总之,TCP四次挥手过程是保证连接可靠性、数据完整性和安全性的重要步骤,是网络通信中必不可少的一部分。

 

有关【Linux-计算机网络】-TCP协议通信流程的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  3. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  4. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  5. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  6. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  7. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  10. arrays - 计算数组中的匹配元素 - 2

    给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at

随机推荐