Java 通过Spring集成向套接字端口发送消息并接收响应
现状Java 通过Spring集成向套接字端口发送消息并接收响应,java,spring,tcp,spring-integration,Java,Spring,Tcp,Spring Integration,现状 在linux服务器上,有几个JAR使用套接字运行—侦听和响应字符串消息 在wildfly应用服务器中运行的新war正在将请求委托给这些套接字 WAR正在使用spring,尤其是spring与注释的集成 我有一个配置类,其中包含services@configuration/@enableeintegration/@IntegrationComponentScan 我已经创建了一个消息网关 @MessagingGateway(defaultRequestChannel = "testGat
- 在linux服务器上,有几个JAR使用套接字运行—侦听和响应字符串消息
- 在wildfly应用服务器中运行的新war正在将请求委托给这些套接字
- WAR正在使用spring,尤其是spring与注释的集成
@MessagingGateway(defaultRequestChannel = "testGateway")
public interface TestGateway{
public Future<String> sendMessage(String in);
}
消息在接收数据时应转换为字符串,在发送数据时应转换为字节
@MessageEndpoint
public static class TestMessage {
@Transformer(inputChannel = "testChannel")
public String convert(final byte[] bytes) {
return new String(bytes);
}
@Transformer(inputChannel = "testGateway")
public String convertResult(final byte[] bytes) {
return new String(bytes);
}
}
应用程序已部署,但响应总是超时。套接字正在运行。我只想要一个简单的直接双向连接:warjar
有人能帮我或给我一个提示吗
------更新-1----------
套接字正在接收消息,但无法读取响应,因为在发送消息后套接字已关闭
------更新-2----------
- 那是个打字错误。系统返回一个MessageHandler
- 我将工厂添加为spring管理的bean
- 我已将“\r\n”添加到旧代码中
- 应用程序仍在抱怨“等待响应超时”
final OutputStream os = serverSocket.getOutputStream();
final PrintWriter pw = new PrintWriter(os, true);
final BufferedReader br = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
final String incoming = br.readLine();
final String response= "ok\r\n";
pw.println(response);
pw.flush();
Thread.sleep(5000);
pw.close();
serverSocket.close();
------更新-3----------
来自Spring的TcpOutboundGateway未收到响应
connection.send(requestMessage);
Message<?> replyMessage = reply.getReply();
if (replyMessage == null) {
connection.send(请求消息);
Message replyMessage=reply.getReply();
if(replyMessage==null){
连接工厂需要是一个@Bean
,以便Spring能够管理它
public TcpInboundGateway testGate() {
final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959); // already running socket
connectionFactory.setApplicationEventPublisher(new NullEventPublisher());
final TcpOutboundGateway gate = new TcpOutboundGateway();
gate.setConnectionFactory(connectionFactory);
gate.setOutputChannelName("testChannel");
return gate;
}
这将无法编译;返回类型与您返回的不匹配
假设这只是一个输入错误,并且bean实际上是一个出站网关,使用此配置,应答必须使用\r\n
(CRLF)终止
请参阅;向下滚动到
TCP是一种流协议;这意味着必须为通过TCP传输的数据提供某种结构,以便接收方可以将数据划分为离散消息。连接工厂配置为使用(de)序列化程序,用于在消息负载和通过TCP发送的位之间进行转换。这是通过分别为入站和出站消息提供反序列化程序和序列化程序来实现的。提供了许多标准(反)序列化程序
…并阅读有关标准反序列化程序的信息。根据您的配置,标准反序列化程序正在等待术语\r\n
(CRLF)
服务器代码的作用是什么
编辑
@SpringBootApplication
public class So49046888Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(So49046888Application.class, args);
String reply = ctx.getBean(TestGateway.class).sendMessage("foo").get();
System.out.println(reply);
Thread.sleep(10_000);
ctx.close();
}
@Bean
public ServerSocket serverSocket() throws IOException {
return ServerSocketFactory.getDefault().createServerSocket(5959);
}
@Bean
public ApplicationRunner runner(TaskExecutor exec) {
return args -> {
exec.execute(() -> {
try {
while (true) {
Socket socket = serverSocket().accept();
final OutputStream os = socket.getOutputStream();
final PrintWriter pw = new PrintWriter(os, true);
final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String incoming = br.readLine();
System.out.println(incoming);
final String response= "ok\r\n";
pw.print(response);
pw.flush();
Thread.sleep(5000);
pw.close();
socket.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
});
};
}
@Bean
public TaskExecutor exec() {
return new ThreadPoolTaskExecutor();
}
@Bean
@ServiceActivator(inputChannel = "testGateway")
public MessageHandler testGate() {
final TcpOutboundGateway gate = new TcpOutboundGateway();
gate.setConnectionFactory(connectionFactory());
gate.setReplyChannelName("toString");
gate.setRemoteTimeout(60_000);
return gate;
}
@Transformer(inputChannel = "toString")
public String transform(byte[] bytes) {
return new String(bytes);
}
@Bean
public AbstractClientConnectionFactory connectionFactory() {
final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
connectionFactory.setSoTimeout(300000);
return connectionFactory;
}
@MessagingGateway(defaultRequestChannel = "testGateway")
public static interface TestGateway {
public Future<String> sendMessage(String in);
}
}
@springboot应用程序
公共类SO49046888应用程序{
公共静态void main(字符串[]args)引发异常{
ConfigurableApplicationContext ctx=SpringApplication.run(SO490468888Application.class,args);
字符串reply=ctx.getBean(TestGateway.class).sendMessage(“foo”).get();
System.out.println(回复);
睡眠(10_000);
ctx.close();
}
@豆子
public ServerSocket ServerSocket()引发IOException{
返回ServerSocketFactory.getDefault().createServerSocket(5959);
}
@豆子
公共应用程序运行程序运行程序(TaskExecutor exec){
返回参数->{
exec.execute(()->{
试一试{
while(true){
套接字=服务器套接字().accept();
final OutputStream os=socket.getOutputStream();
最终PrintWriter pw=新的PrintWriter(os,真);
final BufferedReader br=新的BufferedReader(新的InputStreamReader(socket.getInputStream());
最终输入字符串=br.readLine();
系统输出打印项次(输入);
最终字符串响应=“确定\r\n”;
打印(响应);
pw.flush();
睡眠(5000);
关闭();
socket.close();
}
}
捕获(例外e){
e、 printStackTrace();
}
});
};
}
@豆子
公共任务执行器exec(){
返回新的ThreadPoolTaskExecutor();
}
@豆子
@ServiceActivator(inputChannel=“testGateway”)
public MessageHandler testGate(){
最终TcpOutboundGateway门=新的TcpOutboundGateway();
setConnectionFactory(connectionFactory());
gate.setReplyChannel名称(“toString”);
gate.setRemoteTimeout(60_000);
返回门;
}
@变压器(inputChannel=“toString”)
公共字符串转换(字节[]字节){
返回新字符串(字节);
}
@豆子
公共抽象ClientConnectionFactory connectionFactory(){
final AbstractClientConnectionFactory connectionFactory=新的TcpNetClientConnectionFactory(“本地主机”,5959);
connectionFactory.setSoTimeout(300000);
返回连接工厂;
}
@MessagingGateway(defaultRequestChannel=“testGateway”)
公共静态接口测试网关{
公共未来发送消息(字符串输入);
}
}
编辑了我的问题,以提供更多详细信息。我建议您打开org.springframework.integration的调试级别日志记录;您将获得许多有助于跟踪情况的信息。调试模式没有什么新功能:TcpNetConnectio读取异常localhost:5959:55274:d08ffe-f2a9-465f-9165-956db23adbdb SocketException:Socket closed您现在使用Java序列化而不是默认的CRLF序列化-我用一个工作示例编辑了我的答案。您还应该在服务器上使用pw.print()
,而不是println()
,以避免额外的\n
。如果您想使用println
,请使用
@SpringBootApplication
public class So49046888Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(So49046888Application.class, args);
String reply = ctx.getBean(TestGateway.class).sendMessage("foo").get();
System.out.println(reply);
Thread.sleep(10_000);
ctx.close();
}
@Bean
public ServerSocket serverSocket() throws IOException {
return ServerSocketFactory.getDefault().createServerSocket(5959);
}
@Bean
public ApplicationRunner runner(TaskExecutor exec) {
return args -> {
exec.execute(() -> {
try {
while (true) {
Socket socket = serverSocket().accept();
final OutputStream os = socket.getOutputStream();
final PrintWriter pw = new PrintWriter(os, true);
final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
final String incoming = br.readLine();
System.out.println(incoming);
final String response= "ok\r\n";
pw.print(response);
pw.flush();
Thread.sleep(5000);
pw.close();
socket.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
});
};
}
@Bean
public TaskExecutor exec() {
return new ThreadPoolTaskExecutor();
}
@Bean
@ServiceActivator(inputChannel = "testGateway")
public MessageHandler testGate() {
final TcpOutboundGateway gate = new TcpOutboundGateway();
gate.setConnectionFactory(connectionFactory());
gate.setReplyChannelName("toString");
gate.setRemoteTimeout(60_000);
return gate;
}
@Transformer(inputChannel = "toString")
public String transform(byte[] bytes) {
return new String(bytes);
}
@Bean
public AbstractClientConnectionFactory connectionFactory() {
final AbstractClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory("localhost", 5959);
connectionFactory.setSoTimeout(300000);
return connectionFactory;
}
@MessagingGateway(defaultRequestChannel = "testGateway")
public static interface TestGateway {
public Future<String> sendMessage(String in);
}
}