Spring Integration двусторонняя связь с GPS-устройствами - PullRequest
0 голосов
/ 02 мая 2018

Мы используем приложение интеграции Spring для получения данных с устройств GPS. Для текущей конфигурации мы можем получать данные с устройства, а также повторно отправлять их обратно на устройство по тому же соединению

текущая конфигурация как

@SpringBootApplication
@IntegrationComponentScan
public class SpringIntegrationApplication extends SpringBootServletInitializer{ 

private Integer TIMEOUT=1000*60*10;

    @Value("${TCP_PORT}")
    private Integer TCP_PORT;

    public static void main(String[] args) throws IOException {
        ConfigurableApplicationContext ctx = SpringApplication.run(SpringIntegrationApplication.class, args);       
        System.in.read();
        ctx.close();
    }

    @Bean
    TcpNetServerConnectionFactory cf(){
        TcpNetServerConnectionFactory connectionFactory=new TcpNetServerConnectionFactory(TCP_PORT);

        connectionFactory.setSerializer(new CustomSerializerDeserializer());
        connectionFactory.setDeserializer(new CustomSerializerDeserializer());
        connectionFactory.setSoTimeout(TIMEOUT);
        return connectionFactory;
    }

    @Bean
    TcpInboundGateway tcpGate(){

        TcpInboundGateway gateway=new TcpInboundGateway();
        gateway.setConnectionFactory(cf());
        gateway.setRequestChannel(requestChannel());
        gateway.setRequestTimeout(TIMEOUT);
        return gateway;
    }

    @Bean
    public MessageChannel requestChannel(){

        return new DirectChannel();
    }
}

и конечная точка сообщения

@MessageEndpoint 
public class Echo { 

    @ServiceActivator(inputChannel="requestChannel")
    public byte[] echo(byte[] in,@SuppressWarnings("deprecation") @Header("ip_address") String ip){
        //here we receive packet data in bytes from gps device
        return  "".getBytes();//string will contains expected result for device.
    }

Вышеуказанная конфигурация прекрасно работает для односторонней связи. но мы хотим реализовать двустороннюю связь. Что мы хотим после установления соединения между сервером и устройством, мы хотим отправить сообщение явно. Чтобы отправить команду через сервер, мы не знаем ip и порт устройства, так как мы можем отправить команду через сервер на подключенное устройство.

Я пытаюсь найти решение

создан адаптер исходящего канала

@Bean       
    public TcpSendingMessageHandler tcpSendingMessageHandler() {
        System.out.println("Creating outbound adapter");
        TcpSendingMessageHandler outbound = new TcpSendingMessageHandler();
        return outbound;
    }

затем создал шлюз для явной отправки сообщения, это будет вызываться из службы, в которую мы хотим отправлять данные явным образом

@MessagingGateway(defaultRequestChannel="toTcp")
    public static interface tcpSendService {    
        public byte [] send(String string);
    }

После вызова шлюза путем вызова активатора службы, когда мы устанавливаем ip и порт соединения, эти ip и порты будут от соединения, установленного при получении данных от устройства

@ServiceActivator(inputChannel="toTcp", outputChannel="fromTcp")    
    public String send(String in){              
        System.out.println(new String(in));     
        TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory(ip_extracted_from_inbound_connection, port_extarcted_from_inbound_connection);
        factory.start();        
        tcpSendingMessageHandler.setConnectionFactory(factory);                     
        return in;
    }

// для извлечения ip и порта я использую следующий сервис, который является входящим sevice

@ServiceActivator(inputChannel="requestChannel")
    public byte[] echo(byte[] in,@Header("ip_address") String ip){              
        System.out.println(new String(in)+ " ; IP : "+ip);

        for (String connectionId : factory.getOpenConnectionIds()) {
            if(!lastConection.contains(ip))
                lastConection = connectionId;               
        }

        return "hello".getBytes();
    }

Для активатора сервиса я устанавливаю новый TcpNetClientConnectionFactory при каждом вызове сервиса. Ip и порт извлекаются из TcpNetServerConnectionFactory. всякий раз, когда устройство подключается к серверу, я сохраняю его ip и порт соединения, используя эти ip и порт для передачи данных через сервер, но у меня возникает проблема с тайм-аутом соединения.

Пожалуйста, помогите мне и предложите мне решение по этому вопросу.

Спасибо.

1 Ответ

0 голосов
/ 02 мая 2018

Замените шлюз парой Сотрудничающих адаптеров исходящего и входящего канала .

Для отправки произвольных сообщений в соединение необходимо установить заголовок ip_connectionId.

Задача, однако, заключается в том, как направить ответ на шлюз. Вам нужно будет захватить заголовок replyChannel из запроса и, когда ответ получен на этот ip_connectionId, установить заголовки replyChannel.

Это будет работать только в том случае, если у вас есть только один запрос / ответ, ожидающий обработки для каждого устройства за раз, если в ответе отсутствуют какие-либо данные, которые можно использовать для сопоставления его с запросом.

Другая проблема связана с условиями гонки, когда устройство и сервер инициируют запрос одновременно. Вам нужно будет просмотреть данные во входящем сообщении, чтобы узнать, является ли это запросом или ответом.

...