【问题标题】:Socket taking too long to read data (BufferedReader)套接字读取数据的时间过长 (BufferedReader)
【发布时间】:2016-11-10 19:31:14
【问题描述】:

我正在从交换机读取 ISO 消息,并且读取时间过长。如果它在 8 秒内没有得到回复,它甚至需要两分钟来读取整个流和切换会话超时。是否有另一种方法可以在不使用 BufferedReader 的情况下从套接字获取输入流?

        s = new ServerSocket(8777);

        echo("Server socket created.Waiting for connection...");
        //get the connection socket
        conn = s.accept();
        echo("Connection received from " + conn.getInetAddress().getHostName() + " : " + conn.getPort());

        //3. get Input and Output streams
        out = new PrintStream(conn.getOutputStream());
        //out.flush();
        System.out.println(new Date());
        //in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        System.out.println(new Date());
        InputStream  in  = conn.getInputStream();
        message = in.readLine();
        echo("client>" + message);
        System.out.println(new Date());

这里是你可以看到的日志,从开始读取到输出消息的时间相差大约两分钟

Server socket created.Waiting for connection...
Connection received from 11.xx.xx.xx : 51639
Fri Jul 08 11:53:48 EAT 2016
Fri Jul 08 11:53:48 EAT 2016
client>ISO8583-9300004918040387042160708122130801ISO8583-    9300004918040387049160708122230802
Fri Jul 08 11:55:51 EAT 2016

【问题讨论】:

  • 我猜开关不会以 newLine 结束传输 - 因此是滞后。尝试在没有 BufferedReader 的情况下读取字节。 sn-p 中是否存在复制和粘贴错误?声明了两个ins。不应该编译。
  • 仍然无法正常工作。我已经尝试使用此代码,但延迟仍然存在 InputStream in = conn.getInputStream(); byte[] bytes = IOUtils.toByteArray(in); //message = in.readLine(); echo("client>" + bytes.toString()); System.out.println(new Date());
  • "该方法在内部缓冲输入,因此无需使用 BufferedInputStream。"只需从 InputStream 中读取一个合理大小的 'byte[] 缓冲区'。
  • @Fildor 引用来自哪里?
  • @EJP 抱歉,应该已经发布了源代码。 commons.apache.org/proper/commons-io/javadocs/api-release/org/…

标签: java sockets io


【解决方案1】:

猜测:message = in.readLine();等到 endofLine \n。也许你没有发送一些,或者你错过了发送套接字/流的刷新。

【讨论】:

    【解决方案2】:

    您发布的输出不包含行,因此 readLine() 不合适,并且您希望一次一条消息,因此 IOUtils.toByteArray() 也不合适。试试看,错了,read(byte[])

    【讨论】:

      【解决方案3】:

      我猜你应该使用read(byte[]) 并以某种方式检测到消息的结尾。

      我不熟悉 ISO8583,所以你必须弄清楚。可能是它是一个固定长度的消息协议,或者有一个您可以检测到的消息终止符。

      一个典型的例子是:

      private static final int BUFFER_SIZE = 1024; // Or other reasonable value
      
      // ...
      
      byte[] buffer = new byte[BUFFER_SIZE];
      int bytesRead = 0;
      
      // assuming you got the InputStream as "input"
      while ( (bytesRead = input.read(buffer)) > 0 ){ // -1 indicates EOF
          // read bytes are now in buffer[0..bytesRead-1]
          // analyse bytes to maybe add up multiple reads to a complete message.
      }
      

      为简洁起见,我省略了异常处理。

      【讨论】:

      • 循环条件应该是>。如果缓冲区长度为零,您只能得到零,这不是您想要循环的条件:它不会让您到达任何地方。只是一个错误。
      • 谢谢它的工作我已经使用了 ByteArrayOutputStream 并且它不再延迟了。但现在的问题是,当我第一次写入流时,即使我下次写入前一条消息时刷新它仍然存在。 'ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER_SIZE); while ( (bytesRead = in.read(bytes)) > 0 ){ baos.flush(); baos.write(bytes, 0, BUFFER_SIZE); out.println("响应"+baos.toString("UTF-8")); System.out.println(baos.toString("UTF-8")); }'
      • baos.write(bytes, 0, BUFFER_SIZE); 在收到完整消息时清除缓冲区,并且只写入您收到的字节数。那是baos.write(bytes, 0, bytesRead); 您的消息可能完全适合缓冲区,那么它可能不会分布在 2 个或更多读取周期中。如果您可以确定总是这样,只需在每个周期中清除 ByteBuffer。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-13
      • 2017-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-29
      相关资源
      最近更新 更多