Настройка TCP Socket Server для получения / обработки / ответа - PullRequest
0 голосов
/ 28 февраля 2020

Это новый вопрос, следующий за этим старым вопросом и ответом (в частности, комментарий «не комментируйте старые ответы, задайте новый вопрос»), а также эти примеры в GitHub.

Я знаю, что ответ и примеры - это минимальные рабочие «тривиальные примеры», но я недостаточно знаю, как «вещи работают в Spring» (или должны работать), чтобы понять как разложить эти общие c, тривиальные примеры на отдельные серверы и клиенты, которые соответствуют моей цели. В настоящее время у меня есть работающее приложение-демон Spring-Boot, которое клиент / вызывает (без какой-либо «весенней интеграции») унаследованное приложение-демон через TCP-сокет. Это все работает, работает в производстве.

Но теперь передо мной стоит задача перенести устаревший демон в Spring Boot. Поэтому мне нужно только настроить и настроить кэшированное / объединенное в пул соединение TCP «слушатель сокета» на стороне сервера. Однако «клиентские части» существующих (самостоятельных) примеров меня смущают. В моем случае «клиентская сторона» (существующий демон Spring Boot) не изменится и представляет собой отдельное приложение на отдельном сервере, мне нужно только настроить / настроить «серверную» соединение сокетов ( демон "legacy-daemon, недавно перенесенный в Spring Boot").

Я скопировал конфигурацию этого примера (точно) в мой проект миграции старых версий

@EnableIntegration 
@IntegrationComponentScan 
@Configuration
public static class Config {

@Value(${some.port})
private int port;

@MessagingGateway(defaultRequestChannel="toTcp") 
public interface Gateway {

    String viaTcp(String in);

}

@Bean
@ServiceActivator(inputChannel="toTcp") 
public MessageHandler tcpOutGate(AbstractClientConnectionFactory connectionFactory) {
    TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory);
    gate.setOutputChannelName("resultToString");
    return gate;
}

@Bean 
public TcpInboundGateway tcpInGate(AbstractServerConnectionFactory connectionFactory)  {
    TcpInboundGateway inGate = new TcpInboundGateway();
    inGate.setConnectionFactory(connectionFactory);
    inGate.setRequestChannel(fromTcp());
    return inGate;
}

@Bean
public MessageChannel fromTcp() {
    return new DirectChannel();
}

@MessageEndpoint
public static class Echo { 

    @Transformer(inputChannel="fromTcp", outputChannel="toEcho")
    public String convert(byte[] bytes) {
        return new String(bytes);
    }

    @ServiceActivator(inputChannel="toEcho")
    public String upCase(String in) {
        return in.toUpperCase();
    }

    @Transformer(inputChannel="resultToString")
    public String convertResult(byte[] bytes) {
        return new String(bytes);
    }

}

@Bean
public AbstractClientConnectionFactory clientCF() { 
    return new TcpNetClientConnectionFactory("localhost", this.port);
}

@Bean
public AbstractServerConnectionFactory serverCF() { 
    return new TcpNetServerConnectionFactory(this.port);
}

}

... и проект запустится на локальном хосте и "прослушит" порт 10000. Но когда я подключаюсь к сокету из другого локального приложения и отправляю тестовый текст, ничего не возвращается, пока я не закрою приложение прослушивания сокета. Только после того, как приложение для прослушивания сокетов начинает закрываться, ответ (правильный результат в верхнем регистре) go возвращается к отправляющему приложению.

Как заставить «слушателя» нормально возвращать ответ «отправителю», не выключая сначала сервер слушателя?

Или кто-то может привести пример, который показывает ТОЛЬКО настройка на стороне сервера (надеюсь, на основе аннотаций)? (Или отредактируйте пример так, чтобы сервер и клиент были четко отделены?)

1 Ответ

0 голосов
/ 28 февраля 2020

Образцы обычно содержат как клиента, так и сервера, потому что так проще. Но в разделении клиентской и серверной сторон нет ничего особенного. Вот пример использования Java DSL:

@SpringBootApplication
public class So60443538Application {

    public static void main(String[] args) {
        SpringApplication.run(So60443538Application.class, args);
    }

    @Bean
    public IntegrationFlow server() {
        return IntegrationFlows.from(Tcp.inboundGateway(Tcp.netServer(1234)))
                .transform(Transformers.objectToString()) // byte[] -> String
                .<String, String>transform(p -> p.toUpperCase())
                .get();
    }

}
@SpringBootApplication
public class So604435381Application {

    private static final Logger LOG = LoggerFactory.getLogger(So604435381Application.class);

    public static void main(String[] args) {
        SpringApplication.run(So604435381Application.class, args);
    }

    @Bean
    public IntegrationFlow client() {
        return IntegrationFlows.from(Gate.class)
                .handle(Tcp.outboundGateway(Tcp.netClient("localhost", 1234)))
                .transform(Transformers.objectToString())
                .get();
    }

    @Bean
    @DependsOn("client")
    public ApplicationRunner runner(Gate gateway) {
        return args -> LOG.info(gateway.exchange("foo"));
    }

}

interface Gate {

    String exchange(String in);

}

2020-02-28 09: 14: 04.158 INFO 35974 --- [main] com.example.demo.So604435381Application : FOO

...