Java 使用Chrome通过WebSocket发送大数据的问题
我一直在尝试从头开始为我的聊天程序编写一个JavaHTTP服务器,该程序通过WebSocket发送数据,一切都进行得很顺利,直到我开始尝试使用GoogleChrome用我的程序发送大型图像。我发现当chrome向我的服务器发送多帧数据时,它从未发送正确长度的数据。第一帧总是很好,但在第一帧之后的所有帧发送的数字都明显小于该帧包含的数据。例如,它将发送一个帧,表示它包含123字节的数据,而实际上它发送的数据超过100 KB。我在手机上测试过其他浏览器,如firefox和safari,它们似乎不像chrome那样将大数据分割成帧,因此它们没有相同的问题。以下是我的一些结果截图: 初始帧: 以下是它失败的地方: 下面是我的服务器端代码,它从输入流获取数据并将其写入文件:Java 使用Chrome通过WebSocket发送大数据的问题,java,google-chrome,websocket,Java,Google Chrome,Websocket,我一直在尝试从头开始为我的聊天程序编写一个JavaHTTP服务器,该程序通过WebSocket发送数据,一切都进行得很顺利,直到我开始尝试使用GoogleChrome用我的程序发送大型图像。我发现当chrome向我的服务器发送多帧数据时,它从未发送正确长度的数据。第一帧总是很好,但在第一帧之后的所有帧发送的数字都明显小于该帧包含的数据。例如,它将发送一个帧,表示它包含123字节的数据,而实际上它发送的数据超过100 KB。我在手机上测试过其他浏览器,如firefox和safari,它们似乎不像c
byte[] headerdata = new byte[12];
input.read(headerdata, 0, 2);
int frame = (headerdata[0] & 0b10000000) & 0xFF;
long length = (headerdata[1] & 0b01111111) & 0xFF;
System.out.format("Before: %d, Frame: %d%n", length, frame);
if(length == 127){
input.read(headerdata, 0, 12);
length = ((long)(headerdata[0] << 56) & 0xFFFFFFFFFFFFFFFFL | (long)(headerdata[1] << 48) & 0xFFFFFFFFFFFFFFL | (long)(headerdata[2] << 40) & 0xFFFFFFFFFFFFL | (long)(headerdata[3] << 32) & 0xFFFFFFFFFFL | (headerdata[4] << 24) & 0xFFFFFFFFL | (headerdata[5] << 16) & 0xFFFFFFL | (headerdata[6] << 8) & 0xFFFFL | headerdata[7] & 0xFFL)
} else if(length == 126){
input.read(headerdata, 6, 6);
length = ((headerdata[6] << 8) & 0xFFFF | headerdata[7] & 0xFF);
}else{
input.read(headerdata, 8, 4);
}
System.out.println("After: " + length);
int count;
int total = 0;
byte[] buffer = new byte[16384];
boolean done = false;
while(done == false){
count = input.read(buffer, 0, buffer.length);
//System.out.println(count);
for(int i = 0; i < count; i++){
buffer[i] = (byte)(buffer[i] ^ headerdata[(total & 3) + 8]);
total++;
}
fileoutput.write(buffer, 0, count);
System.out.format("Count: %d Left: %d%n", count, (length - total));
if(total >= length){
done = true;
}
}
if(frame == 128) break;
如果能解释为什么我可能无法阅读以下帧的长度,我将不胜感激。我自己也有一些怀疑。感谢您的时间和努力。我发现缓冲区最终溢出,导致数据被误读或丢失,这就是我从帧中获取错误长度值的原因。我通过添加一个if语句来修复它,该语句检查读取的字节数是否接近该帧的长度值,然后只读取剩余的字节,而不是完整的缓冲区大小,以防止溢出。以下是经过修改的代码:
byte[] headerdata = new byte[12];
input.read(headerdata, 0, 2);
int frame = (headerdata[0] & 0b10000000) & 0xFF;
long length = (headerdata[1] & 0b01111111) & 0xFF;
System.out.format("Before: %d, Frame: %d%n", length, frame);
if(length == 127){
input.read(headerdata, 0, 12);
length = ((long)(headerdata[0] << 56) & 0xFFFFFFFFFFFFFFFFL | (long)(headerdata[1] << 48) & 0xFFFFFFFFFFFFFFL | (long)(headerdata[2] << 40) & 0xFFFFFFFFFFFFL | (long)(headerdata[3] << 32) & 0xFFFFFFFFFFL | (headerdata[4] << 24) & 0xFFFFFFFFL | (headerdata[5] << 16) & 0xFFFFFFL | (headerdata[6] << 8) & 0xFFFFL | headerdata[7] & 0xFFL);
}else if(length == 126){
input.read(headerdata, 6, 6);
length = ((headerdata[6] << 8) & 0xFFFF | headerdata[7] & 0xFF);
}else{
input.read(headerdata, 8, 4);
}
System.out.println("After: " + length);
int count;
int total = 0;
byte[] buffer = new byte[16384];
boolean done = false;
while(done == false){
if(length - total > buffer.length) count = input.read(buffer, 0, buffer.length);
else count = input.read(buffer, 0, (int) (length - total));
//System.out.println(count);
for(int i = 0; i < count; i++){
buffer[i] = (byte)(buffer[i] ^ headerdata[(total & 3) + 8]);
total++;
}
fileoutput.write(buffer, 0, count);
//System.out.format("Count: %d Left: %d%n", count, (length - total));
if(total >= length){
done = true;
}
}
if(frame == 128) break;
我还研究了从套接字读取字节流的不同方法,发现也可以使用DataInputStream.readFully。您一直假设读取会填满缓冲区,而不检查流结束或短读。readFully使用DataInputStream.readFully:事实上,其中一些读取可以使用readInt和friends完成。您仍然假设读取填充缓冲区,并且仍然忽略流结束和短读取。你需要解决这个问题,我很困惑。我共享的代码将继续读取,直到它从帧中发送的长度值中读取确切的字节数为止。我的问题是由于过度阅读,导致跳过下一帧的标题。我无法检查流的结尾,因为它在等待时卡住了,我认为这是因为websocket在发送数据后保持打开状态,我不理解您所说的短读是什么意思。