简体   繁体   English

如何改善从套接字读取XML的方式

[英]How can I improve how I read XML from Socket

I am working on a Java client that connects to a server via socket and sends/receives XML messages. 我正在使用通过套接字连接到服务器并发送/接收XML消息的Java客户端。 I know what the schema of the messages will be. 我知道消息的架构是什么。 I have it working currently, but it feels messy and I haven't tested it yet to see how it handles multiple XMLs sent from the server at once. 我目前正在使用它,但是感觉很混乱,我还没有对其进行测试,以查看它如何处理一次从服务器发送的多个XML。

Here is the code: 这是代码:

  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);
    }
  }

the parseReceivedMessage method just takes in a String and converts it to a Document object. parseReceivedMessage方法只接受一个String并将其转换为Document对象。 My question is, is there a better or cleaner way to do this instead of using a StringBuilder? 我的问题是,有没有更好或更干净的方法来执行此操作,而不是使用StringBuilder? I originally wanted to pass an InputStream to the DOM builder parse method. 我最初想将InputStream传递给DOM构建器的parse方法。 I saw some examples making use of ByteArray streams, but I had some issues with those. 我看到了一些使用ByteArray流的示例,但是我遇到了一些问题。 Let me know if anything needs clarification. 让我知道是否需要澄清。

ready() is not a valid test for end of message. ready()不是对消息结尾的有效测试。 Get rid of that and the StringBuilder and the readLine() calls altogether and just pass the input stream directly to the DOM parser. 摆脱它,然后将StringBuilderreadLine()调用,然后将输入流直接传递到DOM解析器。

I would strongly suggest you design a framing protocol around your XML messages. 我强烈建议您围绕XML消息设计一个框架协议。 Prefix each XML message with a length value that specifies how many bytes are being transmitted, then send the XML itself (in bytes, not characters). 给每个XML消息加上长度值的前缀,该长度值指定要传输的字节数,然后发送XML本身(以字节为单位,而不是字符)。 The receiver can then read the length, then read the specified number of bytes and pass them to the XML parser, then read the next length, and so on. 然后,接收方可以读取长度,然后读取指定的字节数,并将其传递给XML解析器,然后读取下一个长度,依此类推。 For example: 例如:

  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);
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM