有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何改进从socket读取XML的方式

我正在开发一个Java客户机,它通过socket连接到服务器并发送/接收XML消息。我知道消息的模式是什么。我目前正在使用它,但感觉很混乱,我还没有测试它,以了解它如何同时处理从服务器发送的多个XML

代码如下:

  private static BufferedReader socketIn;
  private static PrintWriter socketOut;
  private static final String SERVICES_FILE = "/etc/services";

  public static void main(String[] args) {
    int port = getServicePortByName("Service1", "tcp");
    try {
      logger.info("Creating socket port with ip: " + InetAddress.getLocalHost() + " and port: " + port);
      Socket socket = new Socket(InetAddress.getLocalHost(), port);
      socketOut = new PrintWriter(socket.getOutputStream(), true);

      String message = createMessageXML("LOGIN");
      socketOut.println(message);

      socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      StringBuilder inputLine = new StringBuilder();
      String tmp;

      while (true) {
      //loop to keep listening/parsing
        while(socketIn.ready()) {
          tmp = socketIn.readLine();
          inputLine.append(tmp);
        }
        if(inputLine.length() > 0) {
          parseReceivedMessage(inputLine.toString());
        }
        inputLine.replace(0, inputLine.length(), "");
      }

    } catch (UnknownHostException ex) {
      Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
      Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
    }
  }

parseReceivedMessage方法只接收字符串并将其转换为文档对象。我的问题是,有没有更好或更干净的方法来代替使用StringBuilder?我最初希望将InputStream传递给DOM builder解析方法。 我看到了一些使用ByteArray streams的示例,但我对这些有一些问题。如果需要澄清,请告诉我


共 (2) 个答案

  1. # 1 楼答案

    我强烈建议您围绕XML消息设计一个框架协议。在每个XML消息前面加上一个长度值,该值指定要传输的字节数,然后发送XML本身(以字节为单位,而不是以字符为单位)。然后,接收方可以读取长度,然后读取指定数量的字节并将它们传递给XML解析器,然后读取下一个长度,依此类推。例如:

      private static DataInputStream socketIn;
      private static DataOutputStream socketOut;
      private static final String SERVICES_FILE = "/etc/services";
    
      public static void main(String[] args) {
        int port = getServicePortByName("Service1", "tcp");
        try {
          logger.info("Creating socket port with ip: " + InetAddress.getLocalHost() + " and port: " + port);
          Socket socket = new Socket(InetAddress.getLocalHost(), port);
          socketIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
          socketOut = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    
          byte[] message = createMessageXML("LOGIN");
          socketOut.writeInt(message.length());
          socketOut.write(message, 0, message.length());
    
          int len = socketIn.readInt();
          if (len > 0)
          {
              message = new byte[len];
              socketIn.readFully(message);
              parseReceivedMessage(message);
          }
    
        } catch (UnknownHostException ex) {
          Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
          Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
      }
    
  2. # 2 楼答案

    ready()不是消息结尾的有效测试。去掉这个StringBuilderreadLine()调用,直接将输入流传递给DOM解析器