一种心跳包异步控制方法及装置与流程

文档序号:12477733阅读:245来源:国知局
一种心跳包异步控制方法及装置与流程

本发明涉及心跳包控制技术领域,特别涉及一种心跳包异步控制方法及装置。



背景技术:

心跳包通常是客户端每隔一小段时间向服务器发送的数据包,通知服务器自己仍然在线,并传输一些可能有必要的数据,服务端收到后回复一个固定信息,如果服务端在规定的时间内没有收到客户端信息则视客户端断开。因按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。心跳包的内容没有特别规定,一般都是很小的包或者只是包含包头的一个空包。

心跳包在可穿戴式设备与远程服务器通信当中非常关键,因为目前大部分穿戴式设备都是采用GRPS网络与远程服务器进行双向通信,当网络运营商检测到GPRS数据终端在一定时间内没有传输数据,就会将该连接掐断,因此需要一种机制,在用户没有数据收发的时候来保证连接不会被掐断。心跳包的设置正是为了解决上述问题,心跳包的设置也方便远程服务器进行在线监测。

目前有一种普遍的方法是采用TCP/IP协议层内置的KeepAlive功能来实现心跳功能,不论是服务端还是客户端,一方开启KeepAlive功能后,就会自动在规定时间内向对方发送心跳包,而另一方在收到心跳包后就会自动回复,以告诉对方我仍然在线。该机制简单可靠,但存在如下缺点:SO_KEEPALIVE无法控制,它会每时每刻都发;SO_KEEPALIVE设置空闲2小时才发送一个“保持存活探测分节”,不能保证实时检测,因此对于判断网络断开时间太长,对于需要及时响应的程序不太适应。当然也可以修改时间间隔参数,但是会影响到所有打开此选项的套接口,关联了完成端口的socket可能会忽略掉该套接字选项。另外比较常用的另一种方法是采用多线程,在接收和发送数据时个人设计一个守护进程,定时发送Heart-Beat包,客户端/服务器收到该小包后,立刻返回相应的包即可检测对方是否实时在线。但上述方法的缺点在于:对于操作系统而言,进程和线程的开辟,如果在线客户端数量庞大,那么无论是客户端的心跳包监测,还是例行的数据接收和发送,都要频繁的开辟和销毁线程,这个对系统也是一种不小的开销,而且编程比较复杂,难以保证多线程通信的同步,容易导致线程的死锁。



技术实现要素:

本发明提供了一种心跳包异步控制方法及装置,旨在至少在一定程度上解决现有技术中的上述技术问题之一。

为了解决上述问题,本发明提供了如下技术方案:

一种心跳包异步控制方法,其特征在于,包括:

步骤A:服务器套接字通信参数初始化及服务器通信模型初始化,建立监听套接字描述符;

步骤B:建立和初始化服务器动态链表;

步骤C:初始化并启动控制心跳包的系统定时器;

步骤D:调用监听函数,判断是否有客户端通信事件的触发,如果有客户端通信事件的触发,则服务器主程序退出监听函数,服务器遍历并处理通信事件;如果没有客户端通信事件的触发,则继续等待客户端通信事件的触发。

本发明实施例采取的技术方案还包括:在所述步骤B中,建立的服务器动态链表包括一个头结点和若干结点,每一个结点包括:客户端数据域和存储下一个结点地址的指针域next,每个结点通过指针域next连接起来构成一个动态链表,所述结点的长度等于当前与服务器建立TCP连接的客户端数量;所述客户端数据域包括:存储客户端ID的字符数组类型变量id,存储服务器给当前上线客户端分配的socket文件描述符的整型变量fd,存储丢失的心跳包个数的整型变量heartbeat_lost_count。

本发明实施例采取的技术方案还包括:所述步骤C还包括:启动定时器中断服务函数,通过定时器中断服务函数对服务器动态链表进行遍历,给每一个结点的heartbeat_lost_count按照1的步进递增,对每一个结点的heartbeat_lost_count的值进行判断,如果heartbeat_lost_count大于预设值,则服务器认为该客户端丢失心跳包的时间大于预设值,服务器根据客户端的fd查找客户端所在链表的结点位置,强制将客户端所在的结点删除掉,并给客户端返回错误信息,断开与所述客户端的TCP连接。

本发明实施例采取的技术方案还包括:在所述步骤D中,所述监听函数为epoll_wait函数,所述客户端通信事件包括:新的客户端发起TCP连接请求、已经建立连接的客户端断开TCP连接的请求、已经建立连接的客户端有数据传输和已经建立连接的客户端异常断开TCP连接。

本发明实施例采取的技术方案还包括:在所述步骤D中,监听函数发现触发待处理的事件刚好等于监听套接字描述符socket_fd;根据socket_fd调用accept函数返回新的socket套接字描述符;将侦听到的socket_fd通过epoll_ctl函数添加到epoll句柄当中,已经建立连接的新的客户端如果后续有数据传输,系统利用socket_fd与该客户端进行双向通信。

本发明实施例采取的技术方案还包括:在所述步骤D中,epoll_wait函数发现触发待处理的事件为fd;根据fd调用read函数;判断read返回值是否大于0,如果不大于0,判断read返回值是否等于0,如果read返回值等于0,根据发起断开请求的客户端的fd查找结点所在位置并将结点从链表中删除掉,然后将该删除的结点的前后结点通过结点的指针域next连接起来构成新的链表;如果read返回值不等于0,进行异常处理;read返回值大于0,判断数据包的格式,如果符合预定格式,则对分配给该客户端的fd进行提取,并将它们分别存储到结点的id和fd当中,将fd和id建立映射关系,将该结点添加到动态链表的结尾;如果不符合预定格式,根据协议对其他数据包括或者命令进行判断并处理。

本发明实施例采取的另一技术方案为:一种心跳包异步控制装置,包括:通信参数初始化模块、通信模型初始化模块、动态链表初始化模块、系统定时器启动及初始化模块、监听函数调用模块,所述通信参数初始化模块用于初始化服务器套接字通信参数,建立监听套接字描述符;所述通信模型初始化模块用于初始化服务器通信模型;所述动态链表初始化模块用于建立和初始化服务器动态链表;所述系统定时器启动及初始化模块用于初始化并启动控制心跳包的系统定时器;所述监听函数调用模块用于调用监听函数,判断是否有客户端通信事件的触发,如果有客户端通信事件的触发,服务器主程序退出监听函数,服务器遍历并处理通信事件,如果没有客户端通信事件的触发,则继续等待客户端通信事件的触发。

本发明实施例采取的技术方案还包括:所述服务器动态链表包括一个头结点和若干结点,每一个结点包括两部分:客户端数据域和存储下一个结点地址的指针域next,每个结点通过指针域next连接起来构成一个动态链表,所述结点的长度等于当前与服务器建立TCP连接的客户端数量。

本发明实施例采取的技术方案还包括:所述客户端数据域包括:存储客户端ID的字符数组类型变量id,存储服务器给当前上线客户端分配的socket文件描述符的整型变量fd,存储丢失的心跳包个数的整型变量heartbeat_lost_count。

本发明实施例采取的技术方案还包括:所述系统定时器启动及初始化模块还用于启动定时器中断服务函数,通过定时器中断服务函数对服务器动态链表进行遍历,给每一个结点的heartbeat_lost_count按照1的步进递增,对每一个结点的heartbeat_lost_count的值进行判断,如果heartbeat_lost_count大于预设值,则服务器认为该客户端丢失心跳包的时间大于预设值,服务器将根据客户端的fd查找客户端所在链表的结点位置,强制将客户端所在的结点删除掉,并给客户端返回错误信息,断开与所述客户端的TCP连接。

相对于现有技术,本发明实施例产生的有益效果在于:本发明实施例的心跳包异步控制方法及装置采用linux系统的Epoll服务器模型,简单可靠高效,克服了多线程编程和协议复杂的问题,仅需一个进程就可以实现数以万计的socket通信,此外,采用动态链表的机制来实现客户端上线管理和多客户端心跳包监测,简单且灵活,因链表的长度是跟随用户数量的变化而动态的变化的,因此能够充分利用系统内存资源并高效地对心跳包数据进行处理;客户端发送心跳包的周期可变,针对某客户端,服务器发送心跳包的周期与该客户端发送心跳包的周期一致,如果因为网络故障导致服务器在规定时间内收不到某上线的客户端的心跳包就将对该客户端进行断线的处理。

附图说明

图1是本发明实施例的心跳包异步控制方法的流程图;

图2是本发明实施例的维护客户端通信的链表结构示意图;

图3是心跳包监测的定时器中断服务函数的运行流程图;

图4是本发明实施例的心跳包异步控制方法处理新的客户端发起TCP连接请求的流程图;

图5是本发明实施例的心跳包异步控制方法处理已经建立连接的客户端断开TCP连接的请求或者已经建立连接的客户端发送上线和心跳包命令的事件的流程图;

图6是当前在线的客户端链表的示意图;

图7是有新的客户端上线后的新链表示意图;

图8是已经建立连接的客户端发起断开请求的链表示意图;

图9是将发起断开请求的客户端从链表中删除并重构链表的示意图;

图10是本发明实施例的心跳包异步控制装置的结构示意图;

图11是服务器压力测试模拟示意图;

图12是客户端的TCP/IP调试工具模拟示意图;

图13是上线客户端信息显示图。

具体实施方式

为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅用以解释本发明,并不用于限定本发明。

请参阅图1,是本发明实施例的心跳包异步控制方法的流程图。本发明实施例中的心跳包异步控制方法包括:

步骤10:服务器Socket通信参数初始化,建立监听socket描述符socket_fd;

在步骤10中,Socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。

步骤20:服务器通信模型epoll初始化;

在步骤20中,epoll是一种高效的管理socket的模型。

步骤30:建立和初始化服务器动态链表;

在步骤30中,建立的服务器动态链表是仅包含头结点的链表,用来对客户端进行维护管理,该链表的结点数据结构id_fd_node定义如下:

typedef struct id_fd_str

{

char id[13];//存储ID的字符数组

int fd;//存储Socket的fd

int heartbeat_lost_count;//存储丢失的心跳包个数

struct id_fd_str*next;//存储指向下一个结点的地址

}id_fd_node;

请一并参阅图2,图2是本发明实施例的维护客户端通信的链表结构示意图。该链表包括一个头结点和若干结点,每一个结点包括两部分:客户端数据域和存储下一个结点地址的指针域next,每个结点通过指针域next连接起来构成一个动态链表,头结点指向第一个结点,第一个结点指向第二个结点,依次类推,最后一个结点不再指向其他结点,因此指针域用”null”填充。结点的长度等于当前与服务器建立TCP连接的客户端数量,客户端数据域包括三部分:存储客户端ID的字符数组类型变量id,存储服务器给当前上线客户端分配的socket文件描述符的整型变量fd,存储丢失的心跳包个数的整型变量heartbeat_lost_count。

步骤40:初始化并启动控制心跳包的系统定时器;

在步骤40中,启动控制心跳包的系统定时器后,会启动一个定时器中断服务函数,请一并参阅图3,为心跳包监测的定时器中断服务函数的运行流程图。在定时器中断服务函数中,对链表进行遍历,给每一个结点的heartbeat_lost_count按照1的步进递增,然后对每一个结点的heartbeat_lost_count的值进行判断,如果heartbeat_lost_count大于预设值,那么服务器认为该客户端丢失心跳包的时间大于预设值(流程图中设为5),服务器将根据客户端的fd查找客户端所在链表的结点位置,强制将客户端所在的结点删除掉,那么动态链表的结构和长度将发生变化,并给客户端返回"connection time out!,please online again\r\n"的错误信息,然后断开与该客户端的TCP连接从而强制让其下线。正常情况下,因为服务器会按照客户端发心跳包的频率给客户端回应心跳包(也就是客户端的ID号),并将heartbeat_lost_count清零,因此定时器中断服务函数中的heartbeat_lost_count是不会超过预设值的,只有因为网络原因服务器接收不到客户端的心跳包命令从而不能及时给heartbeat_lost_count清零,导致在定时器中断服务函数中不断的对heartbeat_lost_count递增才会超过预设值。

步骤50:调用监听函数,判断是否有客户端通信事件的触发,如果有客户端通信事件的触发,则进入步骤60,如果没有客户端通信事件的触发,则进入步骤80;

在步骤50中,调用监听函数为epoll_wait函数,客户端通信事件包括:新的客户端发起TCP连接请求、已经建立连接的客户端断开TCP连接的请求、已经建立连接的客户端有数据(命令)传输(包括上线命令和心跳包命令)、已经建立连接的客户端异常断开TCP连接。

步骤60:服务器主程序退出监听函数;

步骤70:服务器遍历并处理通信事件;

步骤80:继续等待客户端通信事件的触发。

在步骤80中,采用阻塞方式继续等待客户端通信事件的触发。

请参阅图4,是本发明实施例的心跳包异步控制方法处理新的客户端发起TCP连接请求的流程图。本发明实施例的心跳包异步控制方法处理新的客户端发起TCP连接请求包括:

步骤100:epoll_wait函数发现触发待处理的事件刚好等于监听套接字描述符socket_fd;

步骤110:根据socket_fd调用accept函数返回新的socket套接字描述符(下文用fd表示);

步骤120:将侦听到的fd通过epoll_ctl函数添加到epoll句柄当中,已经建立连接的新的客户端如果后续有数据传输,那么系统会利用fd与该客户端进行双向通信。

请参阅图5,是本发明实施例的心跳包异步控制方法处理已经建立连接的客户端断开TCP连接的请求或者已经建立连接的客户端发送上线和心跳包命令的事件的流程图。本发明实施例的心跳包异步控制方法处理已经建立连接的客户端断开TCP连接的请求或者已经建立连接的客户端发送上线和心跳包命令的事件包括:

步骤400:epoll_wait函数发现触发待处理的事件为fd(即已经建立连接的客户发起);

步骤401:根据fd调用read函数;

步骤402:判断read返回值是否大于0,如果不大于0,则进入步骤403,如果大于0则进入步骤404;

步骤403:判断read返回值是否等于0,如果read返回值等于0,则进入步骤411,如果read返回值不等于0,则进入步骤412;

步骤404:判断数据包是否为HEL HEL;xxxxxxxxxxx;@的格式,其中HEL是hello的缩写,意思是向服务器打招呼,xxxxxxxxxxx是客户端的ID(手机号),用分号";"隔开,最后以@结束,如果是则进入步骤405,如果不是则进入步骤407;

步骤405:服务器收到“HEL;xxxxxxxxxxx;@”的命令后,将会对xxxxxxxxxxx和分配给该客户端的fd进行提取,并将它们分别存储到结点的id和fd当中以便将fd和id建立映射关系,并对结点中的heartbeat_lost_count初始化为0;

步骤406:将该结点添加到动态链表的结尾,至此,客户端完成了与服务器连接并且上线的操作,那么动态链表的结构和长度将发生变化(如图6,图7所示,图6是当前在线的客户端链表的示意图,图7是有新的客户端上线后的新链表示意图,在图6和图7中,如果有新的客户端发起上线操作,将重复刚才的流程,并在链表的结尾添加新的结点)。

步骤407:判断数据包是否为:HEART;xxxxxxxxxxx;@的格式,其中HEART为心跳包命令同步头,xxxxxxxxxxx为客户端的ID号,如果是则进入步骤408,否则进入步骤410;

步骤408:根据客户端的ID号查找该客户端所在链表当中的结点位置;

步骤409:将查找到的跟该客户端对应的结点中的heartbeat_lost_count清零;

步骤410:根据协议对其他数据包括或者命令进行判断并处理。

步骤411:根据发起断开请求的客户端的fd查找结点所在位置并将结点从链表中删除掉,然后将该删除的结点的前后结点通过结点的指针域next连接起来构成新的链表,假设删除结点编号为2,那么删除前后的链表变化如图8和图9表示。图8是已经建立连接的客户端(结点2)发起断开请求的链表示意图。图9是将发起断开请求的客户端(对应结点2)从链表中删除并重构链表的示意图。

步骤412:进行异常处理。

请参阅图10,是本发明实施例的心跳包异步控制装置的机构示意图。本发明实施例中的心跳包异步控制装置包括:通信参数初始化模块、通信模型初始化模块、动态链表初始化模块、系统定时器启动及初始化模块、监听函数调用模块。

通信参数初始化模块用于初始化服务器Socket通信参数,建立监听socket套接字描述符socket_fd。

通信模型初始化模块用于初始化服务器通信模型epoll,其中,epoll是一种高效的管理socket的模型。

动态链表初始化模块用于建立和初始化服务器动态链表。建立的服务器动态链表是仅包含头结点的链表,用来对客户端进行维护管理,该链表的结点数据结构id_fd_node定义如下:

typedef struct id_fd_str

{

char id[13];//存储ID的字符数组

int fd;//存储Socket的fd

int heartbeat_lost_count;//存储丢失的心跳包个数

struct id_fd_str*next;//存储指向下一个结点的地址

}id_fd_node;

请参阅图2,图2是本发明实施例的维护客户端通信的链表结构示意图。该链表包括一个头结点和若干结点,每一个结点包括两部分:客户端数据域和存储下一个结点地址的指针域next,每个结点通过指针域next连接起来构成一个动态链表,头结点指向第一个结点,第一个结点指向第二个结点,依次类推,最后一个结点不再指向其他结点,因此指针域用”null”填充。结点的长度等于当前与服务器建立TCP连接的客户端数量,客户端数据域包括三部分:存储客户端ID的字符数组类型变量id,存储服务器给当前上线客户端分配的socket文件描述符的整型变量fd,存储丢失的心跳包个数的整型变量heartbeat_lost_count。

系统定时器启动及初始化模块用于初始化并启动控制心跳包的系统定时器;启动控制心跳包的系统定时器后,系统定时器启动及初始化模块会启动一个定时器中断服务函数。请一并参阅图3,为心跳包监测的定时器中断服务函数的运行流程图。在定时器中断服务函数中,对链表进行遍历,给每一个结点的heartbeat_lost_count按照1的步进递增,然后对每一个结点的heartbeat_lost_count的值进行判断,如果heartbeat_lost_count大于预设值,那么服务器认为该客户端丢失心跳包的时间大于预设值(流程图中设为5),服务器将根据客户端的fd查找客户端所在链表的结点位置,强制将客户端所在的结点删除掉,那么动态链表的结构和长度将发生变化,并给客户端返回"connection time out!,please online again\r\n"的错误信息,然后断开与该客户端的TCP连接从而强制让其下线。正常情况下,因为服务器会按照客户端发心跳包的频率给客户端回应心跳包(也就是客户端的ID号),并将heartbeat_lost_count清零,因此定时器中断服务函数中的heartbeat_lost_count是不会超过预设值的,只有因为网络原因服务器接收不到客户端的心跳包命令从而不能及时给heartbeat_lost_count清零,导致在定时器中断服务函数中不断的对heartbeat_lost_count递增才会超过预设值。

监听函数调用模块用于调用监听函数,判断是否有客户端通信事件的触发,如果有客户端通信事件的触发,服务器主程序退出监听函数,服务器遍历并处理通信事件,如果没有客户端通信事件的触发,则继续等待客户端通信事件的触发。

监听函数调用模块调用监听函数为epoll_wait函数,客户端通信事件包括:新的客户端发起TCP连接请求;已经建立连接的客户端断开TCP连接的请求;已经建立连接的客户端有数据(命令)传输(包括上线命令和心跳包命令);已经建立连接的客户端异常断开TCP连接。

请参阅图11、图12和图13,图11是服务器压力测试模拟示意图,图12是客户端的TCP/IP调试工具模拟示意图,图13是上线客户端信息显示图。本发明实施例的心跳包异步控制方法及装置通过TCP/IP调试工具来模拟客户端,用其来发送上线命令和按一定周期发送心跳包,服务器能够按照前面所述流程处理,上线信息显示在前端web网页当中。

本发明实施例的心跳包异步控制方法及装置通过在服务器维护着一个动态链表,链表的长度可弹性缩放,长度取决与当前在线(登陆)的客户端数量,每一个结点代表着一个客户端,一旦有新的客户端发起TCP连接请求,就将其信息填充到新的结点并插入原链表的尾部,一旦已经建立TCP连接的客户端发起断开请求(包括主动发起或者异常断开的情况),服务器就将其从链表结构当中剔除掉。由于链表的结点是根据需要动态开辟的,因此相比需要实现定义固定长度的数组结构而言,极大的提高内存使用效率,由于是通过指针域操作链表的结点,因此访问效率极高。满足了服务器对于海量客户端并发连接和并发通信的高速要求。

另外,定时器中断服务函数触发时间是等间隔的,不受任何客户端心跳包周期的影响,不因客户端心跳包周期的不同和变化,而且可以高速的对链表的结点进行遍历,及时的对异常断开的客户端所在的结点进行清理,从而将内存回收再利用,因此可以实时监测多客户端的并发心跳包并进行客户端上下线管理。

为了提高服务器处理数据的实时性和增强CPU使用效率,服务器采用阻塞方式等待客户端通信事件的触发,只要收到客户端的心跳包,服务器立马返回,因为服务器处理速度极快,因此,服务器给每一个客户端回应心跳包的频率都可以不一样,取决于并且等于该客户端给服务器端发送心跳包的频率。从而增强服务器对客户端的兼容性。

客户端每次上线系统分配的fd都是随机的,具有不确定性,但是在系统中每一个客户端的ID都是固定的,本系统通过上线命令和心态包命令,结合动态链表的建立和操作,可以完美的将fd和用户的ID动态绑定起来,无论客户端在什么终端登录,服务器都能够识别。

本发明实施例的心跳包异步控制方法及装置采用linux系统的Epoll服务器模型,简单可靠高效,克服了多线程编程和协议复杂的问题,仅需一个进程就可以实现数以万计的socket通信,此外,采用动态链表的机制来实现客户端上线管理和多客户端心跳包监测,简单且灵活,因链表的长度是跟随用户数量的变化而动态的变化的,因此能够充分利用系统内存资源并高效地对心跳包数据进行处理。客户端发送心跳包的周期可变,针对某客户端,服务器发送心跳包的周期与该客户端发送心跳包的周期一致,如果因为网络故障导致服务器在规定时间内收不到某上线的客户端的心跳包就将对该客户端进行断线的处理。

对所公开的实施例的上述说明,使本领域专业技术人员能够实现或使用本发明。对这些实施例的多种修改对本领域的专业技术人员来说将是显而易见的,本文中所定义的一般原理可以在不脱离本发明的精神或范围的情况下,在其它实施例中实现。因此,本发明将不会被限制于本文所示的这些实施例,而是要符合与本文所公开的原理和新颖特点相一致的最宽的范围。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1