receive/process/reply 的 TCP 套接字服务器设置
TCP Socket Server setup for receive/process/reply
这是一个新问题,跟进 GitHub 中的 older question and answer (specifically the comment that says "don't comment on old answers, ask a new question"), as well as these 个示例。
我知道答案和示例的工作量很小 "trivial examples",但我对如何 "things work in Spring"(或应该如何工作)知之甚少,无法理解如何将这些通用的、琐碎的示例分解为适合我目的的独立服务器和客户端。我目前有一个正在运行的 Spring-Boot 守护程序应用程序,它是通过 TCP 套接字连接/调用(没有任何 "spring integration")遗留守护程序应用程序的客户端。一切正常,运行 正在生产中。
但现在我的任务是将遗留守护程序也迁移到 Spring Boot。所以我只需要在服务器端配置和设置一个cached/pooled TCP连接"socket listener"。但是,现有(自包含)示例的 "client parts" 让我感到困惑。在我的例子中,"client side"(现有的 Spring 引导守护进程)不会改变,并且是单独服务器上的单独应用程序,我只需要设置/配置 "server-side"套接字连接("legacy-daemon freshly migrated to Spring Boot" 守护进程)。
我已将 this example 配置(准确地)复制到我的遗留迁移项目中
@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 上的 'localhost' 和 "listen" 上启动。但是,当我从另一个本地应用程序连接到套接字并发送一些测试文本时,什么都没有 returns 直到我关闭套接字监听应用程序。只有在套接字侦听应用程序开始关闭后,响应(正确的 'uppercased' 结果)才会返回到发送应用程序。
如何让 "listener" 到 return 正常响应 "sender",而不先关闭侦听器的服务器?
或者有人可以提供一个仅显示服务器端(希望基于注释)设置的示例吗? (或者编辑示例以使服务器和客户端明确解耦?)
示例通常包含客户端和服务器,因为这样更容易。但是,将客户端和服务器端分开并没有什么特别之处。下面是一个使用 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
这是一个新问题,跟进 GitHub 中的
我知道答案和示例的工作量很小 "trivial examples",但我对如何 "things work in Spring"(或应该如何工作)知之甚少,无法理解如何将这些通用的、琐碎的示例分解为适合我目的的独立服务器和客户端。我目前有一个正在运行的 Spring-Boot 守护程序应用程序,它是通过 TCP 套接字连接/调用(没有任何 "spring integration")遗留守护程序应用程序的客户端。一切正常,运行 正在生产中。
但现在我的任务是将遗留守护程序也迁移到 Spring Boot。所以我只需要在服务器端配置和设置一个cached/pooled TCP连接"socket listener"。但是,现有(自包含)示例的 "client parts" 让我感到困惑。在我的例子中,"client side"(现有的 Spring 引导守护进程)不会改变,并且是单独服务器上的单独应用程序,我只需要设置/配置 "server-side"套接字连接("legacy-daemon freshly migrated to Spring Boot" 守护进程)。
我已将 this example 配置(准确地)复制到我的遗留迁移项目中
@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 上的 'localhost' 和 "listen" 上启动。但是,当我从另一个本地应用程序连接到套接字并发送一些测试文本时,什么都没有 returns 直到我关闭套接字监听应用程序。只有在套接字侦听应用程序开始关闭后,响应(正确的 'uppercased' 结果)才会返回到发送应用程序。
如何让 "listener" 到 return 正常响应 "sender",而不先关闭侦听器的服务器?
或者有人可以提供一个仅显示服务器端(希望基于注释)设置的示例吗? (或者编辑示例以使服务器和客户端明确解耦?)
示例通常包含客户端和服务器,因为这样更容易。但是,将客户端和服务器端分开并没有什么特别之处。下面是一个使用 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