title: 如何选择TCP长连接与短连接
author: longzy
time: 2018-11-11
我们在进行linux网络编程时,进程间的通信可选的方案有:socket连接、管道、信号量、共享内存、消息队列等。而通常最好用的也是最常用的方案是socket连接。所以今天主要讲的是tcp连接。
这里并不是要讲我们如何调用API去创建一个tcp的socket连接,而是讲我们在平时的项目中,如何根据自己的业务场景来选择是建立tcp长连接还是tcp短连接。
在这里引入了两个概念:长连接、短连接。那么长连接是什么,短连接又是什么呢?
长连接
从生命周期的角度来理解,长连接的生命周期跟程序的生命周期一样,程序启动的时候会建立好连接,然后程序结束后才主动关闭这个连接。注意这里用到了一个关键词“主动”,也就是长连接过程中会有可能因为其他因素导致这个连接被动断开,这就要求我们在长连接中用什么方法保证连接还存在。(具体的方法后面再讲)
短链接
同样从生命周期的角度来考虑,短连接的生命周期跟栈区的变量一样,好比某个函数里面的局部变量,当外面调用进入到某个函数内部,建立好连接,发送或接受数据,离开函数后,该连接就关闭。
那么我们如何选择长连接还是短连接呢?别急,在讲如何选择之前,我们必须的明白tcp建立连接和关闭连接的这个过程,内部都做了什么工作。
连接建立
啥也别说,先上个图
建立一个TCP连接时会发生下述情形。
- server必须准备好接受外来的连接,这通常是调用socket、bind、和listen等函数来完成。
- client调用connect发起连接,这时client TCP发送一个SYN,告诉server,client将在待建立的连接中发送的数据的初始序列号,通常SYN不携带数据,其所在的IP数据报只含有一个IP首部。
- server必须确认(ACK)client的SYN,同时自己也要发送一个SYN包,它含有server将在同一链接中发送的数据的初始序列号。
- client必须确认server的SYN。
这种交换至少需要三个分组,所以就是我们常说的三路握手,上图展示了3个步骤。上图中client的初始序列号为J,server的初始序列号为K,ACK中的确认号是发送这个ACK的一端所期待的下一个序列号。因为SYN占据一个字节的序列号空间,所以每一个SYN的ACK中的确认号就是该SYN的初始序列号加1。类似的,每一个FIN的ACK中的确认号为该FIN的序列号加1.
连接关闭
同样先来一个图
关闭一个TCP连接时会发生以下情况
- 某个应用程序首先调用close,我们称该端执行主动关闭,该端的TCP于是发送一个FIN,表示数据发送完毕。
- 接收到这个FIN的对端执行被动关闭,这个FIN由TCP确认。它的接收也作为一个文件结束符传递给接收端应用程序,因为FIN的接收意味着接收端应用程序在相应的连接上再无额外数据可接收。
- 一段时间后,接收到这个文件结束符的应用程序叫调用close关闭它的套接字,这导致它的TCP也发送一个FIN。
- 接收到这个最终FIN的原发送端TCP(主动关闭的那一端)确认(ACK)这个FIN
既然每个方向都需要一个FIN和一个ACK,因此通常需要四个分节。这就是我们通常所说的四次挥手。注意,这里我们提到了"通常",是因为存在某些情况,步骤1的FIN可能会随数据一起发送;另外,步骤2和步骤3都是执行被动关闭的那一端发送的,有可能会合并成一步。上图展示了这些步骤。
知道了TCP的连接建立和连接关闭之后,那么数据的发送就可以用下面这个图来解释了
看了上图,我们是不是对前面的提到长连接和短连接更加清楚了!长连接对红线的部分只做一次,而短连接则整个过程,都需要全部重做。
从上面的介绍得知,一个TCP的连接建立和关闭,通常是需要七个分节的。所以长连接和短连接的优缺点也就突显了出来。
连接 | 优点 | 缺点 |
---|---|---|
长连接 | 传输速度快,server可以主动发送数据给client | 保持的连接会占用和多系统资源, 后台设计相对要复杂 |
短连接 | 不需要占用系统的太多的资源使得server可以处理更多client的connect | 发送小数据划不来,比较耗时。server无法主动发送数据到client |
读到这里,你是不是已经对如何选择长连接还是短连接已经有自己的想法了呢?
总结
- 如果业务来往比较频繁,则选择长连接。
- 如果server要主动给client发数据,则选择长连接。