1.4 TCP/IP网络协议
创始人
2024-04-02 08:13:24
0

文章目录

  • 1、浏览器访问网页的过程
  • 2、OSI七层模型
  • 3、TCP三次握手
  • 4、为什么是三次握手不是二次
  • 5、四次挥手
  • 6、为什么是四次挥手,不能是三次挥手吗
  • 7、四次挥手中为什么要有CLOSE-WAIT状态和TIME-WAIT状态
  • 8、什么情况下会出现大量的TIME-WAIT状态?该怎么解决
  • 9、telnet工具使用

1、浏览器访问网页的过程

1、回去DNS域名解析服务器,找到对应的ip地址
2、通过ip地址建立TCP连接
3、浏览器发送HTTP请求,服务器接受请求并处理,服务器返回,浏览器接受请求并渲染信息
4、

2、OSI七层模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
TCP通信流程调用的函数:
客户端

1、socket()创建socket
2、connect()像服务器发送连接请求
3、连接成功之后就行read(),write()处理
4、close()关闭连接

#include 
#include 
#include 
#include 
#include int main()
{// 1、创建socketint nfd = socket(AF_INET,SOCK_STREAM,0);// 准备服务端ip和端口地址struct sockaddr_in ser_addr;ser_addr.sin_family = AF_INET;ser_addr.sin_port = htons(8000);inet_pton(AF_INET,"172.16.244.6",&(ser_addr.sin_addr.s_addr));// 建立连接connect(nfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));// 连接成功之后先写数据char buf[1024] = "hello 服务器,我是客户端\n";write(nfd,buf,sizeof(buf));// 等待server回复memset(buf,0,sizeof(buf));read(nfd,buf,sizeof(buf));printf("服务器发来信息:%s",buf);// 断开连接close(nfd);return 0;
}

服务端:

1、socket()创建socket
2、bing()ip地址和端口号
3、listen()设置同时与服务器建立连接上限数
4、accept()等待连接请求
5、有客户端连接之后,进行read(),write()处理
6、close()关闭连接

#include 
#include 
#include 
#include 
#include 
#define PORT 8000int main()
{// 1、创建socketint nfd = socket(AF_INET,SOCK_STREAM,0);// 2、绑定ip和端口struct sockaddr_in ser_addr,clit_addr;ser_addr.sin_family = AF_INET;ser_addr.sin_port = htons(PORT);ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);bind(nfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr));// 3、设置最大连接数listen(nfd,128);// 等待客户端连接socklen_t clit_len = sizeof(clit_addr);int ncfd;char buf[1024] = {0};char ip_buf[16] = {0};ncfd = accept(nfd,(struct sockaddr*)&clit_addr,&clit_len);printf("%s:%d客户端连接成功!!!\n",inet_ntop(AF_INET,&(clit_addr.sin_addr.s_addr),ip_buf,sizeof(ip_buf)),ntohs(clit_addr.sin_port));// 读信息read(ncfd,buf,sizeof(buf));printf("%s:%d客户端发来消息:%s",inet_ntop(AF_INET,&(clit_addr.sin_addr.s_addr),ip_buf,sizeof(ip_buf)),ntohs(clit_addr.sin_port),buf);memset(buf,0,sizeof(buf));strcpy(buf,"hello world\n");// 写信息write(ncfd,buf,sizeof(buf));// 关闭socketclose(ncfd);close(nfd);return 0;
}

3、TCP三次握手

TCP三次握手是指,客户端和服务器建立连接,一共发送3个数据包才能完成连接,客户端在调用connect函数时就会触发三次握手流程,
在这里插入图片描述

刚开始客户端处于 closed 的状态,服务端处于 listen 状态。然后
1、第一次握手:客户端给服务端发一个 SYN 报文,并指明客户端的初始化序列号 ISN(c)。此时客户端处于 SYN_Send 状态。
2、第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的 SYN 报文作为应答,并且也是指定了自己的初始化序列号 ISN(s),同时会把客户端的 ISN + 1 作为 ACK 的值,表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。
3、第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,当然,也是一样把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 establised 状态。
4、服务器收到 ACK 报文之后,也处于 establised 状态,此时,双方以建立起了链接。

说明:

(1)SYN=1 表示该报文不携带数据,但消耗一个序号 seq=x,seq=x是客户端的初始化序列号,因为tcp是面向字节流的
(2)SYN=1 表示该报文不携带数据,但消耗一个序号 seq=y,seq=y是服务器的初始化序列号,ACK=1是一个确认号
ack=x+1,表示服务器下次接收到的序号希望是x+1。然后服务器进入到SYN-RCVD等待的状态
(3)ACK=1是一个确认号,seq=x+1是上一次服务器回应的序号要求,ack=y+1表示客户下一次接收到的序号希望是y+1

三次握手的作用:
三次握手的作用也是有好多的,多记住几个,保证不亏。例如:
1、确认双方的接受能力、发送能力是否正常。
2、指定自己的初始化序列号,为后面的可靠传送做准备。
3、如果是 https 协议的话,三次握手这个过程,还会进行数字证书的验证以及加密密钥的生成到。

  单单这样还不足以应付三次握手,面试官可能还会问一些其他的问题,例如:

1、(ISN)是固定的吗?

  三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果ISN是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

2、什么是半连接队列

  服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。这里在补充一点关于SYN-ACK 重传次数的问题: 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超 过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s, 2s, 4s, 8s, …

三次握手过程中可以携带数据吗

很多人可能会认为三次握手都不能携带数据,其实第三次握手的时候,是可以携带数据的。也就是说,第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。

为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。也就是说,第一次握手可以放数据的话,其中一个简单的原因就是会让服务器更加容易受到攻击了。
而对于第三次的话,此时客户端已经处于 established 状态,也就是说,对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据页没啥毛病。

当进行第一次握手,网络不好可能会堵塞,所以连接的请求并没有到达服务器端;
但是tcp连接有超时重传的机制,所以再一次发送请求,这时候服务器端接收到了你的请求,他也会返回一个请求给你,这是第二次握手;
但是这时候网络环境突然又好了起来,那个堵塞的请求到达了服务器端,服务器端又给你回了一个请求,但是你又不想给服务器发送请求,这时候服务器的资源会进行占用等待你的请求,为了不使服务器的资源继续占用,你又必须发送一个请求给服务器;
所以要进行3次握手

转载:https://www.cnblogs.com/zzjdbk/p/13028290.html

4、为什么是三次握手不是二次

(1)三次握手目的是确认双方的接收与发送能力是否正常,同步连接双方的初始化序列号 ISN,为后面的可靠性传输做准备。而两次握手只有服务端对客户端的起始序列号做了确认,但客户端却没有对服务端的初始序列号做确认,不能保证传输的可靠性。
(2)三次握手可以防止已失效的连接请求报文段突然又传送到了服务端,导致服务器错误地建立连接,浪费服务端的连接资源。

如果客户端发出的第一个连接请求报文并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达服务器侧。本来这是一个早已失效的报文,但服务器收到此失效的连接请求报文后:

(1)假设不采用“三次握手”,那么只要Server发出确认,新的连接就建立了。但由于现在Client并没有发出建立连接的请求,因此不会理睬Server的确认,也不会向Server发送数据。而Server却以为新的连接已经建立,并一直等待Client发来数据,这样,Server的很多资源就白白浪费掉了
(2)采用“三次握手”协议,只要Server收不到来自Client的确认,就知道Client并没有要求建立请求,就不会建立连接了。

5、四次挥手

数据通信结束后,通信的双方都可以释放连接,将连接关闭掉。连接关闭时将会走四次挥手的流程如下图所示:
在这里插入图片描述

1、第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
2、第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态。
3、第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
4、第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
5、服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。

这里特别需要主要的就是TIME_WAIT这个状态了,这个是面试的高频考点,就是要理解,为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。这其中的原因就是,要确保服务器是否已经收到了我们的 ACK 报文,如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。
至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方成功就是 ACK 报文,此时处于 CLOSED 状态。

6、为什么是四次挥手,不能是三次挥手吗

如果只是三次挥手,那就相当于服务器端发送完第三次挥手的报文后直接进入CLOSED(关闭)状态,假如此时网络出现问题,丢失了第三次挥手的报文,相当于客户端没有收到,那他依旧认为连接没有结束,在一段时间没有收到第二次ACK应答报文后,他会重新发送请求断开连接的报文,但是服务器端已经关闭,不会再接收报文,又形成了类似死锁的情况。

7、四次挥手中为什么要有CLOSE-WAIT状态和TIME-WAIT状态

对于CLOSE-WAIT状态,因为服务器端收到断开TCP连接请求时,有可能还有数据没有向客户端发送完毕,需要一段时间来把所有信息传输完毕。

对于TIME-WAIT状态,假设客户端发送完第四次挥手的报文后,直接进入CLOSED(关闭)状态。那么假设此时网络出现问题,报文丢失,那么因为服务器端收不到第四次挥手的ACK报文段,所以认为此时TCP连接还没有断开。然后重发ACK+FIN报文段,但此时客户端已经关闭与其的TCP连接,肯定不会再接收该报文,这样会浪费大量资源。

8、什么情况下会出现大量的TIME-WAIT状态?该怎么解决

在高并发且短连接的通信情况下,服务器会出现大量TIME-WAIT状态,这占用了大量的socket,会影响服务器的正常通信服务。解决办法有:

(1)降低time_wait的时限;
(2)设置中允许重用time_wait的socket;
(3)设置快速回收time_wait的socket。

9、telnet工具使用

telnet ip 端口号

部分内容转载:https://blog.csdn.net/chenlycly/article/details/127067195

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...