TCP协议之长连接和短连接
前言
TCP在真正开始进行数据传输之前,Server 和 Client 之间必须建立一个连接。当数据传输完成后,双方不再需要这个连接时,就可以释放这个连接。
TCP连接的建立是通过三次握手,而连接的释放是通过四次挥手。所以说,每个TCP连接的建立和释放都是需要消耗资源和时间成本的。
TCP短连接
模拟一种TCP短连接的情况:
- client 向 server 发起连接请求
- server 收到连接请求,双方建立TCP连接
- client 向 server 发送消息
- server 回应 client 消息
- 一次读写完成,此时双方任何一方都可以发起关闭连接请求,即close操作。
在步骤5中,一般都是 client 先发起close操作。从上面的描述来看,短连接一般只会在 client 和 server 之间传递一次读写操作。
短连接的操作过程:建立连接 ——> 传输数据 ——> 关闭连接。
TCP长连接
模拟一种长连接的情况:
- client 向 server 发起连接请求
- server 收到连接请求,双方建立TCP连接
- client 向 server 发送消息
- server 回应 client 消息
- 一次读写完成,TCP连接不关闭
- 后续读写操作...
- 长时间操作之后,client 发起关闭连接请求
TCP长连接是指在连接成功建立之后,即使通信双方没有数据传输也要保持连接,使其不断开。
长连接的操作步骤:建立连接 ——> 传输数据 ——> ... (保持连接) ... ——> 传输数据 ——> 关闭连接
长连接和短连接的优缺点
短连接的优缺点
优点:管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。
缺点:由于TCP的建立和关闭操作需要一定的系统开销,如果客户端连接请求频繁,会降低服务器的处理速度、浪费系统资源和带宽。
长连接的优缺点
优点:长连接可以省去较多的TCP连接的建立和关闭的操作,减少浪费,节约时间。
缺点:client 与 server 之间的连接如果一直不关闭的话,会存在一个问题,随着客户端的连接越来越多,服务器的负载压力会增大,降低服务器的整体性能,更严重者,可能导致服务器崩溃;其次,如果大量处于连接状态的TCP通信双方长时间没有进行数据传输,这也会浪费系统和网络资源。
相关视频推荐
长连接/短连接的应用场景
- 长连接一般多用于需要频繁进行读写操作,点对点通讯,而且连接数不太多的情况。
例如:数据库的连接通常使用长连接,如果用短连接的话,频繁的TCP socket创建和关闭,会造成socket错误,也是对资源的一种浪费。
- 短连接一般用于不需要频繁进行读写操作,并且连接数很大的情况下。
例如:web网站的http服务一般都用短连接。因为长连接对于服务器来说是要耗费一定的系统资源的,像web网站服务,通常会有大量的客户端连接请求,并发连接量大,使用短连接会更节省系统资源,能够及时响应客户请求。
总结:长连接和短连接的选择要具体需求、实际情况而定。
长连接的保活机制
对于TCP长连接,当通信双方在没有数据传输的时候,如何保持TCP连接一直处于“保活(KeepAlive)”状态,这是一个必须要解决的问题。
在Linux系统中,我们可以使用 netstat、lsof等命令可以查看TCP连接是否处于“ESTABLISHED”状态。
TCP保活的必要性
(1)很多防火墙会主动关闭空闲的socket。
(2)可能出现的非正常断连,服务器并不能检测到,为了回收已断连的socket资源,必须提供一种检测机制。
导致TCP非正常断连的可能原因:
(1)网络故障
(2)客户端/服务端一侧突然断电或者进程崩溃
保活机制的方式
6.2.1 应用层的心跳机制
在应用层中使用心跳(heartbeat)机制来主动检测。具体做法:当TCP连接建立成功后,客户端开启一个定时任务,定时对已经建立连接的对端发送一个心跳请求消息,服务器收到该心跳消息后,返回一个心跳应答消息。如果在超时时间内没有收到服务器的应答消息,则重发心跳请求消息,如果客户端持续多次没有响应,客户端则可以认为该TCP连接不可用,主动断开连接。当然,也可以是服务器端主动发送心跳请求消息给客户端。
TCP协议自带的保活机制
Linux内核自带的保活机制keep-alive。使用的时候只需要打开keep-alive功能即可。
TCP的Keepalive机制的作用是在于探测连接的对端是否存活。
工作原理:TCP keep-alive是通过在空闲时发送TCP Keep-Alive数据包,然后对方回应TCP Keep-Alive ACK来实现的。
在socket网络编程中,需要设置一个socket选项 SO_KEEPALIVE,才能开启keepalive机制。代码描述如下:
1 2 3 | keepAlive = 1; setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)); |
在Linux的keepalive机制中,有3个重要的内核参数:tcp_keepalive_time、tcp_keepalive_probes 和 tcp_keepalive_intvl。