客户端/服务器以块的形式传输字节数组,堆空间错误

时间:2016-06-16 11:07:33

标签: java

我需要在客户端到服务器之间发送一个~500kb的字节数组,有时会出现堆空间错误(尝试创建大约1或2gb的字节数组)。' -Xmx'命令不要帮助

字节数组结构[包大小] + [数据块]

此处的代码。

客户端:

public class Client_mk1 {
public static void main(String[] args) throws IOException {

        Socket socket = new Socket("localhost", 3030);
        Client_mk1 clientMk1=new Client_mk1();

        FileInputStream fileInputStream=null;

        File file = new File("SOMEFILE");

        byte[] data = new byte[(int) file.length()];

        System.out.println("file size"+(int) file.length());
        fileInputStream = new FileInputStream(file);
        fileInputStream.read(data);
        fileInputStream.close();
        clientMk1.ToChunks(socket,data);


}

void ToChunks (Socket socket, byte[] data) throws IOException {

    BufferedOutputStream outputstream = new BufferedOutputStream(socket.getOutputStream());

    int chunksize =   50*1024;
    int length = data.length;

    for (int i = 0; i < length - chunksize + 1 ; i+= chunksize) {

        byte[] datasize =IntToByteArray(chunksize);
        ByteBuffer byteBuffer = ByteBuffer.allocate(chunksize + datasize.length);

        System.out.println("TRY TO SEND "+IntFromByteArray(datasize));

        byteBuffer.put(datasize);
        byteBuffer.put(Arrays.copyOfRange(data, i, i + chunksize));
        outputstream.write(byteBuffer.array());

        outputstream.flush();
    }
    if (length % chunksize !=0){
        byte[] datasize = IntToByteArray(length % chunksize);
        ByteBuffer bytebuffer = ByteBuffer.allocate((length % chunksize) + datasize.length);
        System.out.println("TRY TO SEND "+IntFromByteArray(datasize));
        bytebuffer.put(datasize);
        bytebuffer.put(Arrays.copyOfRange(data, length - length % chunksize, length));
        outputstream.write(bytebuffer.array());

        outputstream.flush();
    }
}

public static byte[] IntToByteArray(int value) {
    return new byte[] {
            (byte)(value >> 24),
            (byte)(value >> 16),
            (byte)(value >> 8),
            (byte)value };
}
public static int IntFromByteArray(byte[] bytes) {
    return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

服务器:

public class Server_mk1 implements Runnable {
Socket socket;

Server_mk1(Socket socket){
    this.socket=socket;
}

public static void main(String[] args) throws IOException {
    ServerSocket serversocket = new ServerSocket(3030);

    while (true){
        Socket socket = serversocket.accept();
        Thread dd=new Thread(new Server_mk1(socket));
        dd.start();
    }



}

public void run() {


    BufferedInputStream bufferedInputStream = null;
    try {
        bufferedInputStream = new BufferedInputStream(this.socket.getInputStream());
    } catch (IOException e) {
        e.printStackTrace();
    }



    while (true){
        try {
            byte[] size=new byte[4];

            System.out.println("Reading");
            bufferedInputStream.read(size);

            System.out.println("SIZE "+Client_mk1.IntFromByteArray(size));

            //PROBLEM HERE create to big array for java heap space
            byte[] recievedData=new byte[Client_mk1.IntFromByteArray(size)];//PROBLEM create to big array for java heap space
            bufferedInputStream.read(recievedData);


            System.out.println(new String(recievedData));
        }catch (Exception e){

            break;
        }

    }
    System.out.println("RUNNING ON _"+Thread.currentThread().getName());
}

我做错了什么?

1 个答案:

答案 0 :(得分:2)

你做了很多错事。细微的细节包括在任何地方写socket.getOutputStream(),这简直太荒谬了。您的ByteBuffer代码看起来比将数据写入套接字要复杂得多,并且由于某种原因您正在使用for循环,可能是因为您并不真正了解套接字通信的工作原理。

您的客户端代码可以替换为以下内容(soutSocketOutputStream)。

sout.write(IntToByteArray(data.length));
sout.write(data);
sout.close();

您的服务器已损坏,因为您正在使用available()并且您不明白它的作用。简而言之,不要使用available(),你永远不需要它,它永远不会帮助你。从InputStream读取数据的基本习惯如下

byte[] buf = new byte[8192];  // A smallish buffer to read the bytes
int bytesRead = 0;  // Track the amount of bytes we actually read
while((bytesRead = in.read(byte) != -1) {  // -1 indicates end of stream
    // buf now contains bytesRead amount of new bytes to be processed
}

我有点困惑,因为您正在使用SocketsByteBuffer,但其余代码看起来非常业余。