网络协议 (五) TCP握手建立连接

article/2025/10/1 18:44:20

一、握手策略

为了可以准确的将数据准确无误地送达目标主机,所有基于 TCP 实现的协议,都需要先完成 TCP 协议的三次握手策略。

1. 首先我们需要了解一下图中提到的几个标志符:

1.序号seq
seq 是TCP通信过程中,某一个传输方向上字节流的第一个字节的序号,当发起方发送数据时,会对此进行标记。通过这个序号seq,来确认发送数据的有序性。比如:客户端的序列号为1000,发送了1000,下一次发送的序列号就是2000,以此类推。
2.确认序号ack
ack 是TCP对上一次通信中序号seq做出的确认号,将接收到的序号seq加1  ack = seq + 1。但是只有ACK标志位为1时,确认序列号才有效。
3.标志位
   标志位包括:URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:
   SYN:同步标志位,用于建立会话连接、同步序号seq。
   ACK:确认标志位,对已收到的数据包进行确认。确认序号是否有效,ACK为1时表示有效,
              为0时表示无效。
   FIN: 完成标志位,表示已经没有数据要发送了,关闭一个连接。
   PSH:推送标志位,接收方应该尽快将这个报文交给应用层。
   RST:重置连接。
   URG:紧急指南有效。
   注意⚠️
   序号ack 和 标志位ACK 是不同的两个概念,不要混淆。
   

2. 三次握手描述

所谓三次握手,是指建立一个TCP连接时,需要客户端和服务端相互总共发送3个报文。
第一次握手:
客户端将TCP报文标志位SYN置为1,表示请求建立连接,并随机产生一个序号值seq=x,保存在TCP首部的序列号字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端的确认。
第二次握手:
服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN 和ACK都置为1,ack=x+1,并随机产生一个序号值seq=y,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:
客户端收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给服务器端,服务器端检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
为什么需要三次握手呢?
因为client客户端发出的连接,可能会在某个网络节点长时间滞留,当延误到某个连接释放后的某个时间才到达server服务端时,这已经是一个失效的报文段了,但服务器也会处理相应连接请求。如果不是三次握手,那么这个时候,这个失效的报文就会导致连接成功,但一直不会发送任何
数据,而服务端确一直等待接收数据,这会导致服务端不必要的资源浪费,因此,需要三次握手。

二、挥手策略

四次挥手即终止一个TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个数据包,以确认连接的断开。
第一次挥手:
客户端发起挥手请求,向Server端发送标志位为FIN的报文段,设置序列号seq,此时Client端进入FIN_WAIT_1状态,这表示Client端没有数据要发送给Server端了。
第二次挥手:
Server端收到了Client端发送的FIN报文段,向Client端返回一个标志位是ACK的报文段,ack设为  
seq加1,Server端进入FIN_WAIT_2状态,Server端告诉Client端,我确认并同意你的关闭请求。
第三次挥手:
Server端向Client端发送标志位是FIN的报文段,请求关闭连接,同时Client端进入LAST_ACK状态。
第四次挥手:
Client端收到Server端发送的FIN报文段,向Server端发送标志位是ACK的报文段,然后Client端
进入TIME_WAIT状态。Server端收到Client端的ACK报文段以后,就关闭连接。此时,Client端等待2MSL的时间后依然没有收到回复,则证明Server端已正常关闭,Client端也可以关闭连接了。

为什么需要四次挥手呢?

因为只有在客户端和服务端都没有数据要发送的时候才能断开TCP。而客户端发出FIN报文时只能保证客户端没有数据发了,服务端还有没有数据发客户端是不知道的。而服务端收到客户端的FIN报文后只能先回复客户端一个确认报文来告诉客户端我服务端已经收到你的FIN报文了,但我服务端还有一些数据没发完,等这些数据发完了服务端才能给客户端发FIN报文(所以不能一次性将确认报文和FIN报文发给客户端,就是这里多出来了一次)。

Client为什么需要等待2MSL才关闭呢?

MSL表示报文最大生存时间,超过这个时间,报文将被丢弃。2MSL表示两倍的时间。


http://chatgpt.dhexx.cn/article/jDhXtMBY.shtml

相关文章

TCP 握手没成功怎么办?

大家好,我是小林。 之前收到个读者的问题,对于 TCP 三次握手和四次挥手的一些疑问: 第一次握手,如果客户端发送的SYN一直都传不到被服务器,那么客户端是一直重发SYN到永久吗?客户端停止重发SYN的时机是什么…

深入理解TCP三次握手

一、TCP 包头格式 首先,TCP报文是TCP层传输的数据单元,也称为报文段,下面就是TCP包头格式: 接下来我们来看看每个字段的含义: 源端口和端口字号: TCP源端口:源计算机上应用程序端的端口号&…

TCP的三次握手及四次挥手详解

三次握手 三次握手过程: (1)第一次握手:Client将标志位SYN置为1(表示要发起一个连接),随机产生一个值seqJ,并将该数据包发送给Server,Client进入SYN_SENT状态&#xff0c…

C语言中main函数参数使用

在C99标准中定义main函数两种正确的写法 int main(void); int main(int argc, char* argv[]);常见的不标准写法 void main() main()这里主要说明带参数的main函数如何使用 int main(int argc, char* argv[]) {int i;for (i0; i<argc; i)printf("%d: %s\r\n", i…

C语言main函数参数、返回值

C语言main函数返回值&#xff1a; main函数的返回值&#xff0c;用于说明程序的退出状态。如果返回0&#xff0c;则代表程序正常退出&#xff1b;返回其他数字的含义则由系统决定&#xff0c;通常&#xff0c;返回非零代表程序异常退出&#xff0c;即使程序运行结果正确也仍需修…

main 函数的参数说明

C/C语言中的main函数&#xff0c;经常带有参数argc&#xff0c;argv&#xff0c;如下&#xff1a; int main(int argc, char** argv)int main(int argc, char* argv[])这两个参数的作用是什么呢&#xff1f;argc 是指命令行输入参数的个数&#xff0c;argv存储了所有的命令行参…

C++ main函数及main函数的参数

C main函数及main函数的参数 1、main函数的几种形式 int main() int main(int argc) int main(int argc,char** argv)//int main(int argc,char* argv[])2、argc表示命令行参数的个数、argv表示命令行参数的值 &#xff08;1&#xff09;写个小代码&#xff0c;用命令行运行…

带参数的main函数

支持C语言的系统允许main函数有两个参数 int main(int argc,char *argv[]){//argc表示从命令行传入的参数的个数&#xff1b;//argv表示从命令行传入的字符串数组&#xff1b; } 回显命令行参数 #include<stdio.h> int main(int argc,char *argv[]){int i;for(i0;i<…

main主函数参数解析

默认的main函数参数 int main(int argc, char *argv[]) {// 主函数的代码逻辑return 0; }其中&#xff0c;int 是主函数的返回值类型&#xff0c;主函数执行完后会返回一个整数值给操作系统&#xff0c;通常返回值为 0 表示程序正常结束&#xff0c;非 0 的返回值表示程序运行…

C语言main函数参数

常见的C语言的main函数都是不带参数的。因此main 后的括号都是空括号。实际上&#xff0c;main函数可以带参数&#xff0c;这个参数可以认为是main函数的形式参数。C语言规定main函数的参数只能有两个&#xff0c;习惯上这两个参数写为argc和argv。因此&#xff0c;main函数的函…

【C语言】main函数的参数

我们先看看主函数main的参数列表 #include <stdio.h>int main(int argc, char *argv[]) {return 0; }argc是一个整型变量&#xff0c;存储的是主函数的参数个数argv[]是一个字符型指针数组&#xff0c;其中存储的是主函数的参数字符串&#xff0c;是一个参数列表 注意:…

C++中main函数的参数

C中main函数的参数 问题 对于一个C/CPP文件来说&#xff0c;一般都有main函数&#xff0c;一个程序的执行一定会是先从main函数这个入口开始&#xff0c;一个最基本的程序框架大概长这样: #include <stdio.h> int main() {return 0; }但是&#xff0c;我们有时候看到的…

C++ main函数的参数

int main(int argc, char* argv[]) 那main函数的argc和argv参数是什么意思呢&#xff1f; 这两个参数主要是用来保存程序运行时传递给main函数的命令行参数的。 argc&#xff1a;是argument count 的缩写&#xff0c;保存运行时传递给main函数的参数个数。 argv&#xff1a;是…

main函数的参数的含义

转载自&#xff1a;点击链接 链接2 加qq1126137994 微信&#xff1a;liu1126137994 一起学习更多技术&#xff01;&#xff01;&#xff01; 最近学习服务器网络编程&#xff0c;遇到了一个问题&#xff0c;main函数的参数&#xff0c;特意整理资料记录之&#xff01;&#…

C++main函数及参数

转载自&#xff1a;https://www.cnblogs.com/carsonzhu/p/5276317.html C main()函数及其参数 1、首先&#xff0c;想想C/C在main函数之前和之后会做些什么&#xff1f; 我们看看底层的汇编代码&#xff1a; __start: :      init stack;      init heap;     …

带参数的的main函数

在main()函数中允许带2个参数&#xff0c;一个为整型argc,另一个是指向字符型的指针数组argv[]。格式&#xff1a; int main(int argc,char *argv[])   其中整型argc表示命令行中字符串的个数&#xff0c;指针数组argv[]指向命令行中的各个字符串。这两个参数可以用任何合法…

C语言main函数参数详解

main函数参数 一共有三个&#xff1a; 1.int argc 整型变量 2.char *argv[] 字符指针的数组&#xff0c;通俗一点就是字符串数组&#xff0c;每个元素都是字符串 3.char *envp[] 字符串数组 这三个东西再怎么神秘&#xff0c;也只是函数参数&#xff0c;只不过是main函数的参数…

main函数的参数

main函数可以不带参数,也可以带参数&#xff0c;这个参数可以认为是 main函数的形式参数。C语言规定main函数的参数只能有两个&#xff0c;习惯上这两个参数写为argc和argv。因此&#xff0c;main函数的函数头可写为&#xff1a; main (argc,argv) C语言还规定argc(第一个形参…

main函数的参数解析

下面我们看一下main函数的原型&#xff1a; int main(int argc char* argv[],char* envp) {program-statements } 其实main函数有三个参数&#xff1a; 第一个参数&#xff1a;argc是个整型变量&#xff0c;表示命令行参数的个数&#xff08;含第一个参数&#xff09;。第二…

main 函数参数

一、main函数的参数 main函数有三个参数&#xff0c;argc、argv和envp&#xff0c;它的标准写法如下&#xff1a; int main(int argc,char *argv[],char *envp[])** int argc&#xff0c;存放了命令行参数的个数。 char argv[]&#xff0c;是个字符串的数组&#xff0c;每个元…