目录
本文概览:介绍了OSI七层模型和TCP/IP四层协议、TCP的报文信息、通信和TCP长连接。
1 TCP/IP四层协议
1、OSI
(1)物理层
(2)数据链路层。通信运营
(3)网络层。IP选址和路由选择。
(4)传输层。把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。
(5)会话层。负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。建立、管理和维护会话Session。
(6)表示层。把数据转换为能与接收者的系统格式兼容并适合传输的格式。
(7)应用层。提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如:HTTP、HTTPS、FTP、Telnet、SSH、SMTP、POP3等。
2、TCP/IP分层
网路接口层:网卡、网线。
网络层:IP
运输层 TCP、UPP
应用层。HTTP、FTP等。
2 TCP介绍
2.1 TCP特性
TCP协议是面向字节的。TCP将所要传送的整个报文看成是一个一个字节组成的数据流,并使每一个字节对应于一个序号。TCP属性有:
- 建立连接。TCP提供了客户与服务器之间的连接Conection。类似打电话需要由一个端到端的链路,TCP客户先于某一个服务建立连接,再进行数据交换,最后关闭连接(挂断电话)。
- 可靠性。TCP向另一端发送时,它要求对端返回一个确认。如果没有确认,就进行数次重传,TCP超时等待4~10分钟
- 流控控制。通过TCP的报文头部来告知客户端最大的发送数据大小。
- 全双工。一个连接的两个端,即可以发送数据也可以接受数据。
2.2 TCP报文段解析
- 序号 占4字节,是此报文段的初始地址。
- 确认序号 占4个字节,是期望收到对方的下一个报文段的数据的第一个字节的序号。
- 数据偏移。TCP首部长度。
- URG 当URG=1时,表明紧急指针字段有效,告诉系统此报文段中有紧急数据,需要优先发送
- ACK 只有ACK=1时确认字段才有效。当ACK=0时,确认号无效。
- PSH 希望客户端尽快把数据交付给应用程序
- RST 当RST=1时,表明TCP连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接
- SYN 在连接建立时用来同步序号。
- FIN 用来释放连接,当FIN=1时,表明此报文段的发送端数据已经发送完毕,并要求释放连接。
- 窗口
- 校验和
2.3 与UDP、SCTP比较
UDP:不可靠的、无连接的、提供消息边界的数据报协议
TCP:是基于字节流的,是可靠的、面向连接(以保障通信通畅)的、无消息边界的字节流协议。
SCTP:是基于消息的。
3 建立连接和关闭连接
3.1 端口
一个server接受一个请求创建一个sokcet,分配一个端口,还是和server公用一个接口?一个socketServer绑定和监听一个端口,监听客户端连接,如果客户端有请求过来,就在服务端创建一个socket跟客户端进行通信,所有服务端创建的sokcet共用sockertserver绑定的端口。
(1)单个请求
客户端创建一个socket,分配一个临时端口1500,服务器端通过accept创建一个socket1和clint通信,socket1使用端口就是服务端口8080。
(2)多个请求
另有一个客户端请求时,需要客户端再分配一个临时端口1501,但是服务端通过accept创建的socket1和sockt2 公用服务端接口8080。如下图,
端口划分,如下:
- 0-1023 服务端口。
- 1024-49151,已登记端口
- 49152~655535,临时端口。
3.2 建立连接(三次握手)和 关闭连接(四次握手)
1、建立连接为什么需要三次握手
参考:https://blog.csdn.net/lengxiao1993/article/details/82771768
为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
2、 关闭链接 为什么四次挥手
参考:https://www.zhihu.com/question/63264012/answer/298264454
因为TCP是全双工通信的:
在一端发送了关闭请求之后,另外一端还存在待发送的数据,在发送完成之后,进行第三次挥手,第四次挥手是对第三次数据act,TCP要求每次请求都需要有一个ack。
(1)第一次挥手
因此当主动方发送断开连接的请求(即FIN报文)给被动方时,仅仅代表主动方不会再发送数据报文了,但主动方仍可以接收数据报文。
(2)第二次挥手
被动方此时有可能还有相应的数据报文需要发送,因此需要先发送ACK报文,告知主动方“我知道你想断开连接的请求了”。这样主动方便不会因为没有收到应答而继续发送断开连接的请求(即FIN报文)。
(3)第三次挥手
被动方在处理完数据报文后,便发送给主动方FIN报文;这样可以保证数据通信正常可靠地完成。发送完FIN报文后,被动方进入LAST_ACK阶段(超时等待)。
(4)第四挥手
如果主动方及时发送ACK报文进行连接中断的确认,这时被动方就直接释放连接,进入可用状态。
3.2.1 三次握手的和内核函数
https://zhuanlan.zhihu.com/p/109826876
- 服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待;
- 客户端Socket对象调用connect()向服务器发送了一个SYN并阻塞;
- 服务器完成了第一次握手,即发送SYN和ACK应答;
- 客户端收到服务端发送的应答之后,从connect()返回,再发送一个ACK给服务器;
- 服务器Socket对象接收客户端第三次握手ACK确认,此时服务端从accept()返回,建立连接。
3.3 TCP状态流转
https://www.zhoulujun.cn/html/theory/ComputerScienceTechnology/network/2015_0708_65.html
1、TIME_WAIT作用
TCP主动关闭连接的那一方会最后进入TIME_WAIT。主要作用有:
- 可靠实现TCP全双工连接的中止。四次挥手中,A 发 FIN, B 响应 ACK,B 再发 FIN,A 响应 ACK 实现连接的关闭。而如果 A 响应的 ACK 包丢失,B 会以为 A 没有收到自己的关闭请求,然后会重试向 A 再发 FIN 包。如果没有 TIME_WAIT 状态,A 不再保存这个连接的信息,收到一个不存在的连接的包,A 会响应 RST 包,导致 B 端异常响应。此时, TIME_WAIT 是为了保证全双工的 TCP 连接正常终止。
- 准许老的重复报文在网络中消逝。TCP 下的 IP 层协议是无法保证包传输的先后顺序的。如果双方挥手之后,一个网络四元组(src/dst ip/port)被回收,而此时网络中还有一个迟到的数据包没有被 B 接收,A 应用程序又立刻使用了同样的四元组再创建了一个新的连接后,这个迟到的数据包才到达 B,那么这个数据包就会让 B 以为是 A 刚发过来的。此时, TIME_WAIT 的存在是为了保证网络中迷失的数据包正常过期。TIME_WAIT等待2MSL,在TIME_WAIT阶段,端口不会被重新分配,以保证重复报文在网络中消逝。最大分段寿命(MSL, Maximum Segment Lifetime,MSL的默认值有30秒或者2分钟两类,所以2ML大概是1分钟~4分钟),它表示一个 TCP 分段可以存在于互联网系统中的最大时间,由 TCP 的实现,超出这个寿命的分片都会被丢弃。
4 长连接
1、介绍
TCP 本身并没有长短连接的区别 ,长短与否,完全取决于我们怎么用它。
短连接:每次通信时,创建 Socket;一次通信结束,调用 socket.close()。这就是一般意义上的短连接,短连接的好处是管理起来比较简单,存在的连接都是可用的连接,不需要额外的控制手段。
长连接:每次通信完毕后,不会关闭连接,这样可以做到连接的复用。 长连接的好处是省去了创建连接的耗时。
类似于数据库连接池或者线程持池的思路,如在实现HttpClient的时候,比如Sprintg RestTemplate时候都会维护一个连接池:
- 短连接的操作步骤是:建立连接——数据传输——关闭连接…建立连接——数据传输——关闭连接。
- 长连接的操作步骤是:建立连接——数据传输…(保持连接)…数据传输——关闭连接。
2、应用
(1)长连接场景
用于操作频繁,点对点的通讯。在长连接之下,,可以很方便的实现 push 模型。
(2)短连接
WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
3、 HTTP 的 KeepAlive 区别对待
在HTTP 1.0中默认使用的是短连接,而从HTTP 1.1 之后默认的连接都变为长连接,就是将HTTP 的头部,Connection设置为 keep-alive。
- HTTP 协议的 KeepAlive 意图在于连接复用,同一个连接上串行方式传递请求 – 响应数据。
- TCP 的 KeepAlive 机制意图在于保活、心跳,检测连接错误。
有时候我们通过httpClient访问下游服务时候,需要使用短连接,因为此时HttpClient一般都是连接池,所以是长连接,所以此时可以HTTP的Head“Connection:close”,默认情况下是长连接 ,即Connection:Keep-Alive”。
5 Socket连接池
连接池是维护了一堆长连接,在需要的时候就从连接池获取一个,用完之后也不需要断开,把它归还到池里,所以节省了SOCKET建立和关闭的的时间。
5.1 探活
有两种方式:
方式1:TCP的KeepAlive
KeepAlive 机制是在网络层面保证了连接的可用性。KeepAlive 并不是 TCP 协议的一部分,但是大多数操作系统都实现了这个机制(所以需要在操作系统层面设置 KeepAlive 的相关参数)。KeepAlive 机制开启后,在一定时间内(一般时间为 7200s,参数 tcp_keepalive_time)在链路上没有数据传送的情况下,TCP 层将发送相应的 KeepAlive 探针以确定连接可用性,探测失败后重试 10(参数 tcp_keepalive_probes)次,每次间隔时间 75s(参数 tcp_keepalive_intvl),所有探测失败后,才认为当前连接已经不可用。
方式2 应用层定义探活接口。我们在RPC服务端定义一个心跳接口,RPC客户度轮询这个接口。类似于注册中心探活思想,经常通过心跳方式来实现。