Я использую Spring (Integration)
чтобы предложить соединение tcp сокета. У меня есть определенный тайм-аут для этого сокета.
Когда тайм-аут превышен, я не только хочу отключить соединение (которое уже работает), но и вернуть сообщение об ошибке (или не закрыть соединение, а просто вернуть сообщение об ошибке). Это возможно?
@Bean
public TcpConnectionFactoryFactoryBean tcpFactory(Converter converter) {
TcpConnectionFactoryFactoryBean factory = new TcpConnectionFactoryFactoryBean();
factory.setType("server");
factory.setPort("8080");
factory.setSingleUse(true);
factory.setSoTimeout(10000); //10s; how to return error message?
return factory;
}
Обновить:
@Bean
public ApplicationListener<TcpConnectionEvent> tcpErrorListener() {
TcpConnectionEventListeningMessageProducer producer = new TcpConnectionEventListeningMessageProducer();
producer.setEventTypes(new Class[] {TcpConnectionCloseEvent.class});
producer.setOutputChannel(tcpErrorChannel()); //what to do here?
return producer;
}
Фактически любое закрытое соединение испускает TcpConnectionCloseEvent
и вы можете получить с ним дело, используя:
<int-event:inbound-channel-adapter channel="connectionClosedChannel"
event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionCloseEvent"/>
Имея это, вы не только закрываете соединение, но можете делать любую желаемую логику с этим event-flow
.
ОБНОВИТЬ
Чтобы использовать его из JavaConfig:
@Bean
public SmartApplicationListener tcpErrorListener() {
ApplicationEventListeningMessageProducer producer = new ApplicationEventListeningMessageProducer();
producer.setEventTypes(TcpConnectionCloseEvent.class);
producer.setOutputChannel(tcpErrorChannel());
return producer;
}
@Bean
public MessageChannel tcpErrorChannel() {
return new DirectChannel();
}
int-event
?
Требование немного необычное - что сделает клиент, когда он получит сообщение об ошибке?
В настоящее время нет простого способа перехватить таймаут; вы можете это сделать, но вам придется подклассифицировать фабрику соединений и handleReadException()
объекты подключения и переопределить метод handleReadException()
.
Скорее всего, было бы намного проще обрабатывать сокеты непосредственно в вашем собственном компоненте и отправлять сообщения в поток через Messaging Gateway. Или просто сделайте свой компонент подклассом MessagingGatewaySupport
.
В качестве альтернативы вы можете использовать что-то в своем потоке вниз (и не устанавливать тайм-аут). Когда сообщение получено, планируйте задачу для отправки сообщения об ошибке за 10 секунд. Когда придет следующее сообщение, отмените запланированное задание и назначьте новый.