Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.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 客户端服务器EOF错误_Java_Sockets - Fatal编程技术网

Java 客户端服务器EOF错误

Java 客户端服务器EOF错误,java,sockets,Java,Sockets,我的应用程序使用DataInputStream和DataOutputStream在服务器和客户端之间进行通信。客户端将从一个网站向我的应用程序发送请求,因此我创建了一个测试客户端来测试可能来自该网站的输入 我决定使用的方法是,客户端首先发送一个整数,决定要发送的数据的大小,然后再发送数据。所以,我在测试这个方法,它对第一个数据字符串有效,但对第二个数据字符串无效,在第二次尝试时给了我一个EOF错误。我理解为什么它给了我一个EOF,因为客户端关闭了连接,但我仍然没有读取传入的字节,所以流应该还有更

我的应用程序使用DataInputStream和DataOutputStream在服务器和客户端之间进行通信。客户端将从一个网站向我的应用程序发送请求,因此我创建了一个测试客户端来测试可能来自该网站的输入

我决定使用的方法是,客户端首先发送一个整数,决定要发送的数据的大小,然后再发送数据。所以,我在测试这个方法,它对第一个数据字符串有效,但对第二个数据字符串无效,在第二次尝试时给了我一个EOF错误。我理解为什么它给了我一个EOF,因为客户端关闭了连接,但我仍然没有读取传入的字节,所以流应该还有更多的内容可以读取

客户端代码:

Socket socket = new Socket("127.0.0.1", 9000);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
os.writeInt("Test String".length());
os.write("Test String".getBytes());
os.flush();
os.writeInt("String".length());
os.write("String".getBytes());
os.flush();
os.close();
socket.close();
服务器代码:

byte[] data;

try{
    DataInputStream input = new DataInputStream(client.getInputStream());
    DataOutputStream output = new DataOutputStream(client.getOutputStream());
        client.setSoTimeout(SOCKET_TIMEOUT);

    logger.log(Level.INFO, "Client connected with IP: " + client.getInetAddress());

    data = readNextPacket(input);
    if(!(new String(data).contains(PROTOCOL_HEADER)))
        throw new IOException("Invalid request from client.");
    else
        logger.log(Level.INFO, "Valid header: " + new String(data));

    data = readNextPacket(input);
    logger.log(Level.INFO, new String(data));
}catch(IOException e){
    logger.log(Level.SEVERE, e.getMessage(), e);
}finally{
    try {
        client.close();
    } catch (IOException e) {
        logger.log(Level.SEVERE, e.getMessage(), e);
    }
    logger.log(Level.INFO, "FINISHED");
}
ReadNextPackage方法:

private byte[] readNextPacket(DataInputStream stream) throws IOException{
    int bytesToRead = stream.readInt();
    ByteArrayOutputStream os = new ByteArrayOutputStream();

    if(bytesToRead <= MAX_BYTES){
        byte[] data = new byte[bytesToRead];

        while(stream.read(data) != -1 && os.size() < bytesToRead){
            os.write(data);
        }
    }

    return os.toByteArray();
}
好的,如果第一次没有读取整个缓冲区,那么我的readNextPacket方法将读取比指定的更多的数据。因此,我修改了一些代码,通过向read方法添加一个偏移量并减去我已经读取的量来修复它。但是,我意识到这基本上是复制readFully方法,没有理由这样做,所以我只是将其实现到readNextPacket方法中

以下是新的工作代码:

private byte[] readNextPacket(DataInputStream stream) throws IOException{
    int bytesToRead = stream.readInt();
    byte[] data = new byte[bytesToRead];

    stream.readFully(data);
    return data;
}

我建议您使用java.io.ObjectOutputStream.writeObject,而不是先发送长度。。。这里有一个教程:;如果您不想在条件运算符中使用括号,那也没什么错,但这是一个很好的做法。是的,但我不会从Java对象中读取数据,所以我更喜欢使用readInt和writeInt,因为它们只是将读取的前四个字节转换为int。但是,在我的应用程序中,这似乎不是问题,也不应该是问题。您在ReadNextPackage中编写的代码不正确,但我建议您使用writeUTF编写字符串,并使用readUTF读取字符串,而不是手动复制它们的功能,不正确。实际上writeUTF和readUTF使用的协议与我使用的完全不同。我的方法要简单得多,我更喜欢与网站交流。为什么它不正确呢@EJP@EJP您是对的,如果不成功,我将进行另一次读取,但我将第一次读取的内容放入ByteArrayOutputStream,并使用它来计算我已读取的字节数,因此我不会丢失任何字节。我也不使用API方法,因为编写客户机的人不会使用Java,而是更喜欢我使用的方法?如果失败,除了长单词之外,你什么都不读,而是静默地读,下面对这个方法的调用将以奇怪的方式失败。最好是不管发生什么都让它发生,并立即失败,而不是为以后的调试制造噩梦。
private byte[] readNextPacket(DataInputStream stream) throws IOException{
    int bytesToRead = stream.readInt();
    byte[] data = new byte[bytesToRead];

    stream.readFully(data);
    return data;
}