我需要在客户端到服务器之间发送一个~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());
}
我做错了什么?
答案 0 :(得分:2)
你做了很多错事。细微的细节包括在任何地方写socket.getOutputStream()
,这简直太荒谬了。您的ByteBuffer
代码看起来比将数据写入套接字要复杂得多,并且由于某种原因您正在使用for
循环,可能是因为您并不真正了解套接字通信的工作原理。
您的客户端代码可以替换为以下内容(sout
是SocketOutputStream
)。
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
}
我有点困惑,因为您正在使用Sockets
和ByteBuffer
,但其余代码看起来非常业余。