TCP服务器心跳维持方案

正常情况下客户端中断TCP连接时,会发送一个FIN包,进行4次断开握手来通知服务器。但一些异常情况下,如客户端突然断电断网或者网络异常,服务器可能无法得知客户端已断开连接。

尤其是移动网络,TCP连接非常不稳定,所以需要一套机制来保证服务器和客户端之间连接的有效性。

Swoole扩展本身内置了这种机制,开发者只需要配置一个参数即可启用。Swoole在每次收到客户端数据会记录一个时间戳,当客户端在一定时间内未向服务器端发送数据,那服务器会自动切断连接。

使用方法:

$serv->set(array(
    'heartbeat_check_interval' => 5,
    'heartbeat_idle_time' => 10,
));

上面的设置就是每5秒侦测一次心跳,一个TCP连接如果在10秒内未向服务器端发送数据,将会被切断。

高级用法:

使用swoole_server::heartbeat()函数手工检测心跳是否到期。此函数会返回闲置时间超过heartbeat_idle_time的所有TCP连接。程序中可以将这些连接做一些操作,如发送数据或关闭连接。



  • toice

    我负责的这个平台就是这么检测

  • chris_guojn

    请问如何应用呢,做到永不掉线

  • 张兴友

    客户机tcp 发送空包会不会记录时间戳? (客户端windows程序心跳是5秒发空包检测服务器链接是否正常)

  • 梦回唐朝

    你的什么平台呀?拿出来参考参考?

  • 守後

    这个心跳结束的话会回调onclose

  • 555廵

    websocket 发送什么!!好像时间一到就断线

  • play_soso

    手工检测

    使用手工检测,必须不设置,heartbeat_check_interval heartbeat 是否关闭连接参数不起作用 ,真正起作用的是,是否设置了 heartbeat_check_interval 参数 ,如果设置了,调用该方法,就会关闭过时的连接 ,否则,只会返回过时连接 该方法 返回 值

     Array (     
        [0] => 21
     )
    

    手工关闭过时连接实例代码

    $server->tick(1000, function($id) use ($server) {
                    $closeFdArr = $server->heartbeat(false);
                    foreach($closeFdArr as $fd) {
                        $closeRs = $server->close($fd);
                    }
     });
    
    

    自动检测

    设置好检测时间和超时时间就ok了

    $serv->set(array(
        'heartbeat_check_interval' => 5,
        'heartbeat_idle_time' => 10,
    ));
    
    

    另外注意,不能设置 dispatch_mode=1/3时,底层会屏蔽onConnect/onClose事件,这样就无法回调你的close事件了

  • paddy

    貌似不支持TCP自身心跳机制,通过抓包客户端明明有发送心跳包且收到确认包,但服务器还是在heartbeat_idle_time时间到时关闭连接,必须在客户端定时器中手动通过send函数发送数据才行。

  • 当时只道是寻常

    TCP机制的keepalive是检测死连接的,只要客户端没有死掉,服务器会在超过keepidel闲置时间后发送tcp探测包,发送次数是tcp_keepcount次,每次间隔时间tcp_keepinternal,如果客户端都没发送ack确认,服务器才会close这个连接,swoole实现的心跳机制,只要客户端超过一定时间没发送数据,不管这个连接是不是死链接,都会关闭这个连接