简体   繁体   English

为什么在尝试读取DataInputStream时出现EOFException?

[英]Why am I getting EOFException when trying to read DataInputStream?

I'm working on an assignment where I have to make a chat program using Java Socket 's and Thread 's and I can't get it to work. 我正在做一个作业,必须使用Java SocketThread编写聊天程序,但我无法使其正常工作。 I'm getting EOFEception from a DataInputStream . 我从DataInputStream获得EOFEception From what I understand EOFException from DataInputStream means that the stream was closed, but I haven't closed the stream. 据我了解, DataInputStream EOFException表示流已关闭,但我尚未关闭流。

EDIT: I sat down for an hour with my Professor, but she couldn't figure out either, so kudos to anyone who does. 编辑:我和我的教授坐了一个小时,但她也不知道,所以对任何这样做的人都表示敬意。

Chat.java 聊天室

package dev.gigaboy.chat;

import java.io.IOException;
import java.net.Socket;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Screen;
import javafx.stage.Stage;

public class Chat extends Application {

    private static final int WIDTH = 600, HEIGHT = 290;

    private static String name;
    private static IOThread buffThread;

    private static Insets ins = new Insets(2.5, 5, 2.5, 5);
    private static Font fnt = new Font("Calibri", 13);
    public static TextArea chatBox, userBox;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage prmStage) throws Exception {
        ////////// CHAT SCENE //////////
        HBox hbox = new HBox();

        // current message
        TextField tf = new TextField();
        tf.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.ENTER) {
                try {
                    buffThread.getWriter().writeUTF(name + ": " + tf.getText());
                    buffThread.getWriter().flush();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                System.out.println("Buffer Flushed");

                // append message and scroll TextArea to bottom
                chatBox.appendText(name + ": " + tf.getText() + "\n");
                chatBox.selectPositionCaret(chatBox.getLength());
                chatBox.deselect();
                tf.clear();
            }
        });

        // box where messages show up
        chatBox = new TextArea();
        chatBox.setWrapText(true);
        chatBox.setEditable(false);

        // box where users show up
        userBox = new TextArea();
        userBox.setMinSize(140, 250);
        userBox.setMaxSize(140, 250);
        userBox.setEditable(false);

        hbox.getChildren().addAll(chatBox, userBox);

        VBox vbox = new VBox();
        vbox.getChildren().addAll(hbox, tf);
        HBox.setMargin(chatBox, ins);
        HBox.setMargin(userBox, ins);
        VBox.setMargin(tf, ins);

        ////////// CONNECTION SCENE //////////
        VBox connBox = new VBox();

        TextField usr = new TextField("Username");
        usr.setFont(fnt);

        TextField host = new TextField("localhost");
        host.setFont(fnt);

        // set port to only allow positive integers
        TextField port = new TextField("7777");
        port.setFont(fnt);
        port.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                if (!newValue.matches("\\d*")) {
                    port.setText(newValue.replaceAll("[^\\d]", ""));
                }
            }
        });

        Button bttn = new Button("Connect");
        bttn.setFont(fnt);
        bttn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent evt) {
                // connect to server or become server
                try {
                    connect(host.getText(), Integer.parseInt(port.getText()));
                } catch (NumberFormatException | IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                prmStage.setScene(new Scene(vbox, WIDTH, HEIGHT));
                prmStage.setTitle(usr.getText() + " at " + host.getText() + ":" + port.getText());
                name = usr.getText();

                // reposition window
                Rectangle2D scrnBounds = Screen.getPrimary().getVisualBounds();
                prmStage.setX((scrnBounds.getWidth() - WIDTH) / 2);
                prmStage.setY((scrnBounds.getHeight() - HEIGHT) / 2 - 50);
            }
        });

        connBox.getChildren().addAll(usr,host, port, bttn);
        VBox.setMargin(usr, ins);
        VBox.setMargin(host, ins);
        VBox.setMargin(port, ins);
        VBox.setMargin(bttn, ins);


        Scene connScene = new Scene(connBox, 230, 130);
        prmStage.setOnCloseRequest(evt -> {
            try {
                if (buffThread != null)
                    buffThread.close();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            Platform.exit();
            System.exit(0);
        });
        prmStage.setTitle("Connect...");
        prmStage.setScene(connScene);
        prmStage.setResizable(false);
        prmStage.show();
    }

    private static boolean isHostAvailable(String host, int port) {
        try (Socket socket = new Socket(host, port)) {
            return true;
        } catch (IOException e) {

        }

        return false;
    }

    private static void connect(String host, int port) throws IOException {
        if (isHostAvailable(host, port)) {
            buffThread = new ClientThread(host, port);
            System.out.println("CLIENT");
        } else {
            buffThread = new ServerThread(port);
            System.out.println("SERVER");
        }

        buffThread.start();
    }

}

ClientThread.java ClientThread.java

package dev.gigaboy.chat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

import javafx.application.Platform;

public class ClientThread extends IOThread {

    private Socket socket;

    private String host;
    private int port;

    public ClientThread(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public void close() throws IOException {
        socket.close();
        super.close();
    }

    @Override
    public void run() {
        try {
            socket = new Socket(host, port);
            // inherited from BufferedThread
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        while (true) {
            Platform.runLater(() -> {
                try {
                    String line;
                    line = in.readUTF();
                    Chat.chatBox.appendText(line);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

}

ServerThread.java ServerThread.java

package dev.gigaboy.chat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javafx.application.Platform;

public class ServerThread extends IOThread {

    private ServerSocket server;
    private Socket socket;

    private int port;

    public ServerThread(int port) {
        super();
        this.port = port;
    }

    @Override
    public void close() throws IOException {
        server.close();
        socket.close();
        super.close();
    }

    @Override
    public void run() {
        try {
            server = new ServerSocket(port);
            socket = server.accept();

            // inherited from BufferedThread
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        while (true) {
            Platform.runLater(() -> {
                try {
                    String line;
                    line = in.readUTF();
                    Chat.chatBox.appendText(line);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

}

IOThread.java IOThread.java

package dev.gigaboy.chat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class IOThread extends Thread {

    protected DataInputStream in;
    protected DataOutputStream out;

    public IOThread() {

    }

    public DataInputStream getReader() {
        return in;
    }

    public DataOutputStream getWriter() {
        return out;
    }

    public String readUTF() throws IOException {
        return in.readUTF();
    }

    public void close() throws IOException {
        in.close();
        out.close();
    }

}

I think it's likely that readUTF isn't understanding that it should wait for the end of the line character, and that's why this is happening. 我认为readUTF可能不了解它应该等待行字符的结尾,这就是这种情况的原因。

You can make your life much easier using a DataFetcher and a FetcherListener( https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/io ) 您可以使用DataFetcher和FetcherListener( https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/io )使您的生活更加轻松

package tjacobs.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;

import tjacobs.io.TimeOut.TimeOutCmd;

/**
 * DataFetcher is a generic way to read data from an input stream (file, socket, etc)
 * DataFetcher can be set up with a thread so that it reads from an input stream 
 * and report to registered listeners as it gets
 * more information. This vastly simplifies the process of always re-writing
 * the same code for reading from an input stream.
 * @author tjacobs01
 */
    public class DataFetcher implements Runnable, TimeOutCmd {
        public byte[] buf;
        public InputStream in;
        public int waitTime;
        private ArrayList<FetcherListener> mFetcherListeners;
        public int got = 0;
        protected boolean mClearBufferFlag = false;

        public DataFetcher(InputStream in, byte[] buf, int waitTime) {
            this.buf = buf;
            this.in = in;
            this.waitTime = waitTime;
        }

        public void addFetcherListener(FetcherListener listener) {
            if (mFetcherListeners == null) {
                mFetcherListeners = new ArrayList<FetcherListener>(2);
            }
            if (!mFetcherListeners.contains(listener)) {
                mFetcherListeners.add(listener);
            }
        }

        public void removeFetcherListener(FetcherListener fll) {
            if (mFetcherListeners == null) {
                return;
            }
            mFetcherListeners.remove(fll);
        }

        public byte[] readCompletely() {
            run();
            return buf;
        }

        public int got() {
            return got;
        }

        /** Override this to implement other implementations
         * 
         */
        public void timeOut() {
            try {
                if (in != null)
                in.close();
            }
            catch (IOException iox) {
                iox.printStackTrace();
            }
        }

        public void run() {
            TimeOut to = null;
            if (waitTime > 0) {
                to = new TimeOut(this, waitTime);
                Thread t = new Thread(to);
                t.start();
            }           
            int b;
            try {
                if (in == null) {
                    signalListeners(true);
                    return;
                }
                while ((b = in.read()) != -1) {
                    if (to != null) to.tick();
                    if (got + 1 > buf.length) {
                        buf = IOUtils.expandBuf(buf);
                    }
                    int start = got;
                    buf[got++] = (byte) b;
                    int available = in.available();
                    //System.out.println("got = " + got + " available = " + available + " buf.length = " + buf.length);
                    if (got + available > buf.length) {
                        buf = IOUtils.expandBuf(buf, Math.max(got + available, buf.length * 2));
                    }
                    got += in.read(buf, got, available);
                    signalListeners(false, start);
                    if (mClearBufferFlag) {
                        mClearBufferFlag = false;
                        got = 0;
                    }
                }
            } catch (IOException iox) {
                iox.printStackTrace();
                throw new PartialReadException(got, buf.length);
            } finally {
                if (to != null) to.stop();
                buf = IOUtils.trimBuf(buf, got);
                signalListeners(true);
            }
        }

        private void setClearBufferFlag(boolean status) {
            mClearBufferFlag = status;
        }

        public void clearBuffer() {
            setClearBufferFlag(true);
        }

        private void signalListeners(boolean over) {
            signalListeners (over, 0);
        }

        private void signalListeners(boolean over, int start) {
            if (mFetcherListeners != null) {
                Iterator<FetcherListener> i = mFetcherListeners.iterator();
                while (i.hasNext()) {
                    FetcherListener fll = i.next();
                    if (over) {
                        fll.fetchedAll(buf);
                    } else {
                        fll.fetchedMore(buf, start, got);
                    }
                }               
            }
        }

        public static interface FetcherListener {
            public void fetchedMore(byte[] buf, int start, int end);
            public void fetchedAll(byte[] buf);
        }

        public static class ToPrintStream implements FetcherListener {
            PrintStream stream;
            public ToPrintStream(PrintStream ps) {
                stream = ps;
            }

            @Override
            public void fetchedAll(byte[] buf) {
            }

            @Override
            public void fetchedMore(byte[] buf, int start, int end) {
                stream.print(new String(buf, start, end - start));
            }           
        }

        public static class ToStandardOut extends ToPrintStream {

            public ToStandardOut() {
                super(System.out);
            }
        }       
    }

EOFException - if this input stream reaches the end before reading all the bytes. EOFException-如果此输入流在读取所有字节之前到达末尾。

It means that your stream no longer contains any remaining data; 这意味着您的流不再包含任何剩余数据。 you've reached the end of the stream. 您已经到了流的尽头。

try {
        String line;
        line = in.readUTF();
        Chat.chatBox.appendText(line);
    }

should be 应该

try {
        String line;
        while( (line = in.readUTF()) != null ) {
            Chat.chatBox.appendText(line);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM