【问题标题】:Stx/Etx serializer in spring integrationSpring 集成中的 Stx/Etx 序列化程序
【发布时间】:2021-07-05 07:57:23
【问题描述】:

我正在开发一个使用套接字与服务器通信的应用程序。

我在客户端使用 spring 集成,在服务器端使用 java ServerSocket。 我使用 STX/ETX 序列化套接字上的消息以指示消息的开始和结束,为此我使用 spring ByteArrayStxEtxSerializer 类。

但问题是当ByteArrayStxEtxSerializer 用作序列化时,在服务器端或反之亦然接收到的消息有一些延迟,有时消息从未收到。

唯一让我感到困惑的是,当我检查与ByteArrayCrLfSerializer 相同的场景时,整个过程顺利进行,没有任何延迟或失败。

我的客户端和服务器端代码片段如下:

服务器端:

public void startSocketServer(){

  try (final ServerSocket serverSocket = new ServerSocket(9992)) {
       gl.info("Server is listening on: " + serverSocket.getLocalSocketAddress());

     while (true) {
         final Socket socket = serverSocket.accept();
         gl.info("A new client connected");
         new SocketThread(socket).start();
     }
  } catch (IOException e) {
    e.printStackTrace();
  }
}

private class SocketThread extends Thread {
  private final Socket socket;
  private final PrintWriter writer;
  private final BufferedReader reader;

  public SocketThread(Socket socket) throws IOException {
     this.socket = socket;
     InputStream input = socket.getInputStream();
     OutputStream output = socket.getOutputStream();

     reader = new BufferedReader(new InputStreamReader(input));
     writer = new PrintWriter(output, true);
  }
  public void run() {
     try {
         while (true) {
             String inputMessage = reader.readLine();
             if (inputMessage != null) {
                 MessageType messageType = getTypeInstance(inputMessage);

                if (messageType instanceof LoginMessage loginMessage) {
                     if (isAuthenticated(loginMessage.getUsername(), loginMessage.getPassword())) {
                        gl.info("#### SERVER => User authorized");
                        final String messageBody = createConnectionAckMessage();
                        print(writer, messageBody);
                     } else {
                         print(writer, createRefusalMessage());
                     }
                } else if (messageType instanceof StartTransferingData startData) {
                    getMessages().forEach(message-> print(writer, message));

                } else if (messageType instanceof DisconnectionAck disAck) {
                    print(writer, "By then")
                    break;
                }
            }
         }
         socket.close();
     } catch (IOException ex) {
         gl.info("Server exception: " + ex.getMessage());
     }
 }
 private void print(PrintWriter writer, String msg) {
     writer.print(ByteArrayStxEtxSerializer.STX);
     writer.print(msg);
     writer.print(ByteArrayStxEtxSerializer.ETX);
 } 
}

和客户端:

public class CapConfig {

   @MessagingGateway(defaultRequestChannel = "toTcp", errorChannel = "errorChannel")
   public interface TcpGateway {
     @Gateway
     void send(String in);
   }

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

   @Bean
   public AbstractClientConnectionFactory clientCF() {
      return Tcp.netClient("localhost", 9992)
          .serializer(TcpCodecs.stxetx())
          .deserializer(TcpCodecs.stxetx())
          .get();
   }

   @Bean
   public IntegrationFlow tcpOutFlow(AbstractClientConnectionFactory connectionFactory) {
      return IntegrationFlows.from(toTcp())
         .handle(Tcp.outboundAdapter(connectionFactory))
         .get();
   }

   @Bean
   public IntegrationFlow tcpInFlow(AbstractClientConnectionFactory connectionFactory) {
      return IntegrationFlows.from(Tcp.inboundAdapter(connectionFactory))
         .transform(stringTransformer)
         .log()
         //---- Do some other stuffs
         .get();
   } 
}

【问题讨论】:

    标签: java sockets spring-integration


    【解决方案1】:

    问题是reader.readLine(),因为读者搜索\n 来识别行尾。

    我用STX/ETX来表示消息的开始和结束,那我自己去解析吧。

            private String read() throws IOException {
               int bite = reader.read();
               if (bite!= ByteArrayStxEtxSerializer.STX){
                  throw new RuntimeException();
               }
               char[] result = new result[socket.getReceiveBufferSize()]
               while((bite=reader.read())!= ByteArrayStxEtxSerializer.ETX){
                     //-- Collect the bytes and do related stuff
                     result.....
               }
    
               return new String(result);
            }
    

    【讨论】:

    • 答案是正确的。请参阅ByteArrayStxEtxSerializer 实现。
    • 您也可以直接使用ByteArrayStxEtxSerializer(而不是滚动您自己的代码。
    • @GaryRussell 感谢您的评论,我在客户端使用了ByteArrayStxEtxSerializer,它工作正常,该片段代码适用于服务器端。我在服务器端犯了错误。
    猜你喜欢
    • 2015-03-26
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多