【问题标题】:send byte[] to server, outOfMemoryError [duplicate]将字节 [] 发送到服务器,outOfMemoryError [重复]
【发布时间】:2018-05-28 08:03:49
【问题描述】:

我正在尝试使用 ssl 套接字将文件(此处为视频)发送到我的服务器,我可以发送 11 次,但是当我再尝试一次时,我遇到了 OutOfMemoryError,我想知道如何解决这个问题。

客户端(Android):

    InputStream inputStream = null;
    try {
        inputStream = getAssets().open("test.mp4");
    } catch (IOException e) {
        e.printStackTrace();
    }

    byte[] bytes2 = null;

    try {
        bytes2 = getBytes(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }

    if (socketConnect()) {
        try {
            Log.d("MainActivity", "Before OutputStream");
            OutputStream os = sock.getOutputStream();
            Log.d("MainActivity", "Before FileInputStream");
            Log.d("MainActivity", "Before while " + bytes2.length);
            os.write(bytes2);
            Log.d("MainActivity", "After while");
            os.flush();
            os.close();
            sock.close();
            Log.d("MainActivity", "End");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    else {
        Log.e("MainActivity", "Erreur");
    }

服务器端(Python):

import socket
import sys
import ssl


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("",9999))

sock.listen(10)

i=1

while True:
    (clientsocket, (ip, port)) = sock.accept()
    connstream = ssl.wrap_socket(clientsocket,
                                 server_side = True,
                                 certfile = "server.crt",
                                 keyfile = "server.key")
    f = open('test_'+str(i)+".jpg",'wb') #open in binary
    i=i+1
    print(i)
    l = 1
    l = connstream.read(1024)

    while (l):
            print("toto")
            f.write(l)
            l = connstream.read(1024)
    f.close()

    connstream.close()

sock.close()

日志:

05-28 09:56:31.019 11519-11519/com.youstiti.simon.testenvoiwithbuffer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.youstiti.simon.testenvoiwithbuffer, PID: 11519
java.lang.OutOfMemoryError: Failed to allocate a 33552396 byte allocation with 28973408 free bytes and 27MB until OOM
    at java.io.ByteArrayOutputStream.expand(ByteArrayOutputStream.java:91)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:201)
    at com.youstiti.simon.testenvoiwithbuffer.MainActivity.getBytes(MainActivity.java:153)
    at com.youstiti.simon.testenvoiwithbuffer.MainActivity.onCreate(MainActivity.java:73)
    at android.app.Activity.performCreate(Activity.java:6272)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
    at android.app.ActivityThread.access$900(ActivityThread.java:157)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5525)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

我认为缓冲区可以解决问题,但我不知道该怎么做。

感谢您的回答

【问题讨论】:

  • 33552396 字节是一大堆。尝试按块解析和发送。
  • 尝试关闭()你的 InputStream
  • 我该怎么做?
  • 在 build.gradle 中添加 dexOptions{ javaMaxHeapSize "4g" }
  • bytes2 = getBytes(inputStream);。您正在将整个文件放入内存中。正如您现在看到的内存不足问题,这不是必需的并且是错误的方法。你应该按照 tompee 已经告诉你的那样发送夹头。

标签: android arrays sockets buffer


【解决方案1】:

您必须逐块读取和发送文件以避免OOM错误,因为android堆是有限的,如下所示

if (socketConnect()) {
try {
    final int bufferSize = 8*1024;
    FileInputStream fis = new FileInputStream(/*...your file*/);
    byte[] buffer = new byte[bufferSize]; 
    int read;
    OutputStream os = sock.getOutputStream();
    while( ( read = fis.read( buffer ) ) > 0 ){
          os.write(buffer, 0, read);
    }
    os.close();
    fis.close();    
} catch (IOException e) {
    e.printStackTrace();
}
else {
    Log.e("MainActivity", "Erreur");
}

通过添加android:largeHeap="true"避免请求大堆,google说:

永远不要仅仅因为内存不足而请求大堆,并且 你需要快速修复

查看the doc了解更多信息

【讨论】:

  • os.write(buffer) 不正确。它会忽略read() 返回的计数,并且会在输入的末尾写入垃圾,如果不是之前的话。应该是os.write(buffer, 0, read)。 1MB 的缓冲区大小太大了几个数量级。
  • 好的。您不应该在循环内部冲洗。它破坏了可能存在的任何缓冲点:在这种情况下没有缓冲点。修复了这个问题和其他几个问题。
  • 一行:FileInputStream fis = new FileInputStream(/*...你的文件*/);我必须把文件路径正确吗?
  • 感谢您的回答。当我放置文件时,这不起作用,但是当我放置文件的路径时,它可以工作(使用图像),但是当我想发送视频时,我有 outOfMemoryError
  • 好吧,我的错,它与文件一起工作,但我总是在视频中出现 outOfMemoryError
猜你喜欢
  • 2015-07-16
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 2018-10-31
  • 1970-01-01
相关资源
最近更新 更多