Socket.D v2.5.11

客户端会话

</> markdown

客户端会话(ClientSession)是会话接口(Session)的子集。集群客户端会连接多个地址,内部会有多个会话,有些方法不便使用,所以有了 ClientSession 这个子集。非集群模式下,可以强转为 Session。

但因为侧端不同,客户端有自己的一些隐式特点

1、客户端会话

  • ClientSession 关闭
编码描述说明
1000因协议关闭开始(安全关闭)“本端”可以再发消息。心跳继续。但不建议再使用
1001因协议指令关闭“本端”再发消息会尝试重连。心跳继续
1002因协议非法关闭同上
1002因协议非法关闭同上
2001因异常关闭同上
2002因重连关闭同上
2008因打开失败关闭同上
2009因用户主动关闭(不可再重连)给“对端”发送关闭协议帧(成功的话会触发关闭事件)。心跳中止。
“本端”再发消息会异常。需要手动重连后才能再发

如果是服务端的 Sessoin 没有心跳和重连。其它一样。

  • ClientSession 心跳与自动重连

socket.d 是个长连接协议,通过心跳与自动重连保证连接的可靠性。心跳,客户端会定时发送 Ping 协议帧(默认为20秒,可配置)。服务端收到后会答复 Pong 协议帧。

心跳时,如果发现连接是无效的会尝试重新重连。这个也称为“自动重连”。

//配置心跳间隔(单位毫秒)。//更多配置参考“配置类”
ClientSession session = SocketD.createClient("sd:ws://127.0.0.1:8602/?u=a&p=2")
        .config(c->c.heartbeatInterval(20_000)) 
        .open();
  • ClientSession 手动重连与自动重连的区别

自动重连,是由心跳机制触发的行为。在主动调用 session.close() 心跳会取消,不再支持自动重连。如果还需要再连接或发送消息,需要主动调用 session.reconnect()

手动重连,还可以应用在关闭事件里。在关闭时异步尝试重连(能连上去的机率比较低)。

//手动重连应用1(能连上去的机率比较低。刚断开,环境可能不未恢复)
ClientSession sessoin = SocketD.createClient("sd:ws://127.0.0.1:8602/?u=a&p=2")
        .listen(new EventListener().doOnClose((s) -> {
            RunUtils.delay(s::reconnect, 1000);//1秒后尝试一次重连。
        }))
        .open();
        
//手动重连应用2(做单元测试经常会用)
session.close();
session.reconnect();

2、客户端会话接口

  • ClientSession 完整接口(以 Java 为例)
/**
 * 客户会话
 */
public interface ClientSession extends Closeable {
    /**
     * 是否有效
     */
    boolean isValid();
    
    /**
     * 是否关闭中
     * */
    boolean isClosing();

    /**
     * 获取会话Id
     */
    String sessionId();

    /**
     * 手动重连(一般是自动)
     */
    void reconnect() throws IOException;

    /**
     * 发送
     *
     * @param event  事件
     * @param entity 实体
     * @return 流
     */
    SendStream send(String event, Entity entity) throws IOException;

    /**
     * 发送并请求
     *
     * @param event  事件
     * @param entity 实体
     * @return 流
     */
    default RequestStream sendAndRequest(String event, Entity entity) throws IOException {
        return sendAndRequest(event, entity, 0L);
    }

    /**
     * 发送并请求
     *
     * @param event   事件
     * @param entity  实体
     * @param timeout 超时(单位:毫秒)
     * @return 流
     */
    RequestStream sendAndRequest(String event, Entity entity, long timeout) throws IOException;


    /**
     * 发送并订阅(答复结束之前,不限答复次数)
     *
     * @param event  事件
     * @param entity 实体
     * @return 流
     */
    default SubscribeStream sendAndSubscribe(String event, Entity entity) throws IOException {
        return sendAndSubscribe(event, entity, 0L);
    }

    /**
     * 发送并订阅(答复结束之前,不限答复次数)
     *
     * @param event   事件
     * @param entity  实体
     * @param timeout 超时(单位:毫秒)
     * @return 流
     */
    SubscribeStream sendAndSubscribe(String event, Entity entity, long timeout) throws IOException;
    
    /**
     * 预关闭(用于两段式关闭,执行后对端的 session.isClosing() 为 true)
     */
    void preclose() throws IOException;
    
    /**
     * 关闭
     */
    void close() throws IOException;
}