libwebsockets 与Netty websocket库之间的通讯 - housekeeper-software/tech GitHub Wiki

问题

libwebsockets(C++)作为websockets 服务器,netty websocket 作为客户端,连接5分钟后服务器断开与netty客户端的连接。

原因分析

libwebsockets 4.2或者更高版本改变了内部超时机制,通过lws_retry_bo_t 去控制连接的超时。一般,我们在服务器上不去设置此选项,因为系统有默认参数,代码如下所示:

context->default_retry.retry_ms_table = default_backoff_table;
	context->default_retry.conceal_count =
			context->default_retry.retry_ms_table_count =
					LWS_ARRAY_SIZE(default_backoff_table);
	context->default_retry.jitter_percent = 20;
	context->default_retry.secs_since_valid_ping = 300; //notice
	context->default_retry.secs_since_valid_hangup = 310; //notice

	if (info->retry_and_idle_policy &&
	    info->retry_and_idle_policy->secs_since_valid_ping) {
		context->default_retry.secs_since_valid_ping =
				info->retry_and_idle_policy->secs_since_valid_ping;
		context->default_retry.secs_since_valid_hangup =
				info->retry_and_idle_policy->secs_since_valid_hangup;
	}

意思是说,作为 libwebsockets 服务器,对于每条连接,每隔300秒会向客户端发送一个Ping包,如果在10秒内没有收到客户端Pong包回复,则认为客户端已经断开,从而服务器主动断开连接。

解决方案

经过测试,java端使用org.java-websocket包实现websocket client 无此问题。因为内部已经实现了对ping/pong的自动处理。但是netty内部没有默认实现,需要在如下的地方响应:

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   .... //处理其他的业务
    } else if (frame instanceof PingWebSocketFrame) {
      ch.writeAndFlush(new PongWebSocketFrame());
    }
}

至此,问题解决。

其他

到目前为止,只发现 netty 作为客户端的时候有此问题需要注意,其他语言的websocket库一般都有内部默认实现。