kotlin Spring集成Tcp服务器超时,带有自定义反序列化器

kqhtkvqz  于 2023-03-19  发布在  Kotlin
关注(0)|答案(1)|浏览(153)

我声明了一个Tcp入站适配器来接收来自特定客户端的消息,这是一个发送自定义有效负载的硬件设备。没有一个默认的反序列化器可以满足我对客户端发送的消息的需求,所以我实现了一个自定义的反序列化器,如果有任何内容要读取,则读取输入流,然后在链的其他组件中处理有效负载。我也使用拦截器来只接受非空的有效载荷。
我的问题是我需要在超时后关闭连接,但是设置了soTimeOut后,连接在指定的超时后不会关闭。我怀疑是因为反序列化器检测到空输入流,并认为空消息是有效的。
这是使用KotlinDSL的服务器配置

@Bean
    fun tcpServer() = Tcp.netServer(port)
        .leaveOpen(true)
        .deserializer { inputStream ->
            when(inputStream.available()>0){
                true -> inputStream.readNBytes(inputStream.available())
                false -> byteArrayOf()
            }
        }
        .serializer(TcpCodecs.raw())
        .backlog(30)
        .interceptorFactoryChain(interceptor())
        .soTimeout(60000)

这是一个拦截器,用于过滤非空的有效负载以进行进一步处理

class ValidationInterceptor(
    applicationEventPublisher: ApplicationEventPublisher
) : TcpConnectionInterceptorSupport(applicationEventPublisher) {
    override fun onMessage(message: Message<*>): Boolean {
        if ((message.payload as ByteArray).isEmpty()) return false
        return super.onMessage(message)
    }
}
4xrmg8kj

4xrmg8kj1#

请与我们分享如何关闭套接字。soTimeout无法关闭套接字:

/**
 *  Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}
 *  with the specified timeout, in milliseconds. With this option set
 *  to a positive timeout value, a read() call on the InputStream associated with
 *  this Socket will block for only this amount of time.  If the timeout
 *  expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
 *  Socket is still valid. A timeout of zero is interpreted as an infinite timeout.
 *  The option <B>must</B> be enabled prior to entering the blocking operation
 *  to have effect.
 *
 * @param timeout the specified timeout, in milliseconds.
 * @throws  SocketException if there is an error in the underlying protocol,
 *          such as a TCP error
 * @throws  IllegalArgumentException if {@code timeout} is negative
 * @since   1.1
 * @see #getSoTimeout()
 */
public synchronized void setSoTimeout(int timeout) throws SocketException {

另外,您使用的是.leaveOpen(true)。因此,要关闭套接字,您必须以某种方式手动执行TcpConnection.close()。例如,可以从某些代码中使用AbstractConnectionFactory.closeConnection(String connectionId) API,其中您从TCP服务器套接字上接收到的消息中获取IpHeaders.CONNECTION_ID标头。

相关问题