前言
大家应该都知道,在Android端实现TCP长连接场景其实不多,我们最熟悉的不过推送和HTTP协议的实现(OkHttp),本文讨论的是在实现推送长连接的情况下怎么来做性能优化,下文只是我的一点拙见,有不妥之处还望指出,下面话不多说了,来一起看看详细的介绍吧。
推送长连接
可以说大部分APP是离不开推送(push)这个功能的,不过平常我们都是接入第三方SDK(极光、个推等)居多,因为要做一个推送服务,不光客户端要编写相应的Socket通信代码,服务器端更是麻烦,要处理大规模的长连接服务,消息还得及时送达,一两台服务器可是吃不消。相对来说客户端编写Socket通信的代码会简单一些,但是也是要处理一些平台相关的问题,比如推送服务进程如何保活,APP进程如何跟推送服务进程通信,如何节省手机电量和手机弱网情况下如何提升通信质量等一系列的问题。这些问题以后有时间分析,下面来看看TCP长连接性能如何来优化
影响TCP性能的点
TCP/IP体系太复杂了,想完全掌握确实很困难,我们只分析影响TCP性能的几个因素,看看在Android客户端可不可以进行优化
TCP连接的三次握手时延
我们知道要建立TCP连接,需要经过三次握手,三次握手成功后连接建立成功
- 客户端请求新的连接,需要发送一个设置了SYN标记的分组,向服务器说明这三个连接请求
- 如何服务器接受了这个连接请求,会向客户端回送一个设置了SYN和ACK的分组,向客户端说明连接请求已经被接受了
- 客户端收到这个表明连接请求被接受的分组后,要发送一条携带ACK标记的确认消息(可能会在这个消息中携带业务数据)表明连接已经建立成功了,可以开始发送数据了
那建立TCP连接的三次握手而产生的时延对我们会有影响吗,大部分情况下是没有的,只有当HTTP请求传输的数据量比较小,然后呢这样的HTTP请求又非常频繁,这样算下来,握手产生的时延占比就很高了,这种情况下就要通过重用已有的连接来减少连接的次数。而推送长连接本身就是在保持连接的稳定性,无需在这点上进行优化
延迟确认
由于因特网本身无法保证可靠的分组传输,TCP就自己实现确认机制来确保数据的可靠传输,成功接收TCP分组数据的接收者都需要向发送者回送一个小的确认分组,发送者在一定的时间内没有收到这个确认分组,就认为之前发送的数据没有成功,然后会重发数据
但是由于确认分组非常的小,TCP为了有效的利用网络,会把确认分组塞到同向传输数据中去,组合在一起发送传输,如果在一定的时间内没有同向传输数据咋办,岂不是一直会重发?TCP肯定不会允许这种情况发送的,TCP针对这种情况实现了一种延迟确认算法,在一定的窗口时间(一般是100~200毫秒),确认分组还没有被捎带的话,那么确认分组就会单独发送
根据自己之前编写TCP长连接的经验,一般会在应用层设计一个业务ACK包机制,当收到一个业务数据时,马上会回送一个业务层的ACK包,这个业务层的ACK包就是同向传输数据,确认分组马上会被捎带,不会触发延迟确认算法,但是如果我们收到的消息频率很高,那产生的ACK包就会非常的多,再假设业务层的ACK包并不需要那么的及时,我们是否可以组合业务层ACK包再发送呢?
TCP慢启动
TCP连接的性能还受到拥塞控制机制的影响,当TCP连接刚开始连接上时,并不能一下子就发送很多的分组,可能是一开始只能发送一个分组,然后收到确认分组后,就可以发送两个分组,然后就是四个分组,以此类推。这个就是TCP慢启动,发送数据的能力是慢慢提升的
由于我们编写的是长连接,这种机制对我们的影响并不大
Nagle算法
由于TCP并没有规定每个分组最小值,所以我们可以每次都传输一个字节的数据,但是TCP有固定的标记和首部(至少40个字节),如果TCP发送大量的包含少量数据的分组时,网络的真实利用率就很低,网络整体性能会严重的下降。
所以呢TCP利用了Nagle算法,在发送了一个分组前,将大量TCP数据绑定在一起,提高网络的效率。Nagle算法鼓励发送全尺寸的分组,而且只有当所有的分组都被确认后,才能发送非全尺寸的分组,不然的话就缓存起来,直到积累足够发送一个全尺寸分组数据时才会将缓存的数据发送出去
那这个对我们编写TCP长连接时有什么影响呢,由于我们的心跳包和ACK包一般都很小,那么服务端就不能及时收到我们的心跳包和ACK包,会产生时延,可以通过下面的代码来禁用Nagle算法
Socket.setTcpNoDelay(true);
TIME_WAIT累积与端口耗尽
这个跟服务端相关,一般与客户端没什么关系,这里就不说了
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对找一找教程网的支持。