论TCP服务端KeepAlive的对智能穿戴设备的影响

对Socket网络编程有一定的了解,应该对KeepAlive都不陌生。毫不夸张地说,如果不懂KeepAlive,你所编写的TCP服务一定不堪重负。甚至会出现许多在你看来非常莫名其妙的问题。

本文不再对基础的KeepAlive知识作重点介绍。而是重点介绍在对低功耗穿戴产品提供TCP服务时,如何高效使用KeepAlive。

以下我将通过一段文字简单介绍一下Socket KeepAlive相关知识。然后我们再切入正题。

TCP KeepAlive,从字面上看,它能够检测你的 TCP socket  并检测连接是否在运行或者是否已经被破坏。keepalive概念很简单:当建立一个TCP连接时,你将一系列的定时器与该连接相关联。这些定时器中某些用于处理keepalive过程。当keepalive定时器变为0时,你给你的同伴(也就是对方)发送一个keepalive 探针包(probe packet),包内没有数据并且ACK标识打开。另一方面,你会收到一个来自远方主机的回应,该回应没有数据并且设置ACK标识。如果你收到一个对于你的keepalive探针的响应,那么就说明连接正在运行,不必担心用户级别的实现。事实上,TCP允许你控制流,没有包及零长度的数据包对于用户程序而言没有危险。这个过程是有用的。因为如果其他主机失去连接,你就可以注意到连接时断开的。如果keepalive探针没有被响应,那么就可以断言连接不能被认为是有效的,那么就需要采取正确的操作。我们之所以会使用TCP KeepAlive,主要是:1. 服务端,检测dead peers,以便节省服务开销;2. 客户端,阻止因网络连接不活跃而被服务端踢掉。

事实上,TCP KeepAlive并非绝无风险的。在使用时,仍需小心谨慎。

如上文所述,虽然keepalive是无攻击性的,但是它会产生多余的网络带宽,这就会对于路由和防火墙产生影响。而将这个影响放在<TCP Server - 低功耗智能穿戴设备>这对组合上。其影响绝非小事。过于频繁的KeepAlive探测会造成低功耗智能穿戴设备网络通讯一直处于活跃状态,造成设备功耗大幅度升高。

在服务端,我们该如何妥善使用KeepAlive呢?

KeepAlive有3个参数。从以下函数的注释代码,可以知道onOff是KeepAlive的开关,keepAliveTime是开始首次KeepAlive探测前的TCP空闭时间,keepAliveInterval是 两次KeepAlive探测间的时间间隔。结合智能穿戴设备的心跳间隔特点。如何在服务端既要能做到检测dead peers,又要不引起智能穿戴设备的功耗升高。此时,最好将keepAliveTime时间设置成大于智能穿戴设备的心跳间隔,但为了保证检测dead peer的时效性,又不能大过头。如:设备的心跳间隔是5min,则keepAliveTime最好设置成6min。详见以下代码:

/*设置Keep-Alive参数
         * 
         * KeepAlive函数参数说明:
         * onOff:是否开启KeepAlive,0表示停止,1表示开启
         * keepAliveTime:开始首次KeepAlive探测前的TCP空闭时间,单位ms
         * keepAliveInterval: 两次KeepAlive探测间的时间间隔,单位ms
         */      
        private byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
        {
            byte[] buffer = new byte[12];
            BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
            BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
            BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
            return buffer;
        }

 

 /*在接受客户端连接处理时,我们按如下方法调用KeepAlive。
         * 客户端连接处理函数
         * 欲建立服务器连接的Socket对象
         */
        protected virtual void AcceptConn(IAsyncResult iar)
        {
            //如果服务器停止了服务,就不能再接收新的客户端
            if (!_isRun)
            {
                return;
            }
            //接受一个客户端的连接请求
            Socket oldserver = (Socket)iar.AsyncState;
            Socket client = oldserver.EndAccept(iar);
            //检查是否达到最大的允许的客户端数目
            if (_clientCount == _maxClient)
            {
                //服务器已满,发出通知
                if (ServerFull != null)
                {
                    ServerFull(this, new NetEventArgs(new Session(client)));
                }
            }
            else
            {
                client.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 3600000, 1000), null);
                Session newSession = new Session(client);
                _sessionTable.Add(newSession.ID, newSession);
                //客户端引用计数+1
                _clientCount++;
                //开始接受来自该客户端的数据
                client.BeginReceive(_recvDataBuffer, 0, _recvDataBuffer.Length, SocketFlags.None,
                 new AsyncCallback(ReceiveData), client);
                //新的客户段连接,发出通知
                if (ClientConn != null)
                {
                    ClientConn(this, new NetEventArgs(newSession));
                }
            }
            //继续接受客户端
            _svrSock.BeginAccept(new AsyncCallback(AcceptConn), _svrSock);
        }

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值