Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Chrome通过WebSocket发送大数据的问题_Java_Google Chrome_Websocket - Fatal编程技术网

Java 使用Chrome通过WebSocket发送大数据的问题

Java 使用Chrome通过WebSocket发送大数据的问题,java,google-chrome,websocket,Java,Google Chrome,Websocket,我一直在尝试从头开始为我的聊天程序编写一个JavaHTTP服务器,该程序通过WebSocket发送数据,一切都进行得很顺利,直到我开始尝试使用GoogleChrome用我的程序发送大型图像。我发现当chrome向我的服务器发送多帧数据时,它从未发送正确长度的数据。第一帧总是很好,但在第一帧之后的所有帧发送的数字都明显小于该帧包含的数据。例如,它将发送一个帧,表示它包含123字节的数据,而实际上它发送的数据超过100 KB。我在手机上测试过其他浏览器,如firefox和safari,它们似乎不像c

我一直在尝试从头开始为我的聊天程序编写一个JavaHTTP服务器,该程序通过WebSocket发送数据,一切都进行得很顺利,直到我开始尝试使用GoogleChrome用我的程序发送大型图像。我发现当chrome向我的服务器发送多帧数据时,它从未发送正确长度的数据。第一帧总是很好,但在第一帧之后的所有帧发送的数字都明显小于该帧包含的数据。例如,它将发送一个帧,表示它包含123字节的数据,而实际上它发送的数据超过100 KB。我在手机上测试过其他浏览器,如firefox和safari,它们似乎不像chrome那样将大数据分割成帧,因此它们没有相同的问题。以下是我的一些结果截图: 初始帧:

以下是它失败的地方:

下面是我的服务器端代码,它从输入流获取数据并将其写入文件:

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在发送数据后保持打开状态,我不理解您所说的短读是什么意思。