有 Java 编程相关的问题?

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

java从socket和inputStream的慢速读取

我使用java。网在我的应用程序中接收消息的socket。接收速度很慢。接收250 kB的数据持续7秒以上。我可以做些什么来加速这一过程。7秒太长了

InputStream is = null;
byte[] arr = new byte[8192];
try {
    is = client.getInputStream();
} catch (IOException e) {
    e.printStackTrace();
}

int bytesNumber;
StringBuffer sb = new StringBuffer();

try {
    while ((bytesNumber = is.read(arr)) >= 0) {
        if (bytesNumber == 8192) {
            sb.append(arr);
            continue;
        } else {
            for (int i = 0; i < bytesNumber; i++) {
                sb.append(arr[i]);
            }
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

共 (3) 个答案

  1. # 1 楼答案

    这是因为,如果读取的长度小于缓冲区(arr)长度,则会逐个追加一个字符。而是附加整个缓冲区内容,不需要if:

    sb.append(arr,0,butesNumber);
    
  2. # 2 楼答案

    性能如此糟糕不太可能是由于您的代码造成的。在相同的系统之间使用curl或类似的东西可以获得什么样的性能

    更大的问题是,您的代码不太可能实现您想要的功能。当前,您正在将字节数组的表示形式附加到字符串,或将字节的十进制表示形式附加到该字符串。如果服务器发送“你好,世界!”,您将得到一个字符串,上面写着“7210110810811144328711111410810033”。对于较长的文件,您将看到类似于“[B@76c5a2f7“弹出,这就是字节数组的打印方式

    我会这样写,假设您正在接收用UTF-8编码的文本:

    CharArrayWriter str = new CharArrayWriter();
    try (InputStream is = client.getInputStream()) {
      Reader r = new InputStreamReader(is, StandardCharsets.UTF_8);
      char[] buffer = new char[8192];
      while (true) {
        int n = r.read(buffer);
        if (n < 0)
          break;
        str.write(buffer, 0, n);
      }
    }
    System.out.println(str);
    
  3. # 3 楼答案

    正如tinker提到的,通常最大的限制是客户端和服务器网络。但是你可以大大简化你所拥有的。另外,在我看来,您的8K缓冲区太小了。除非有严重的内存限制,否则请使用1M或更大的内存

    public String readClient(Client client) throws IOException{
        final int bufferSize = 1024 << 9;
    
        BufferedInputStream in = new BufferedInputStream(client.getInputStream(),bufferSize);
        byte[] bytes = new byte[bufferSize];
        int bytesRead;
        StringBuilder sb = new StringBuilder(bufferSize);
        try {
            while ((bytesRead = in.read(bytes)) != -1) {
                sb.append(new String(bytes, 0, bytesRead));
            }
        }finally {
            in.close();
        }
        return sb.toString();
    }