Получение «java.io.EOFException» после отправки файла через сокет - PullRequest
1 голос
/ 30 октября 2011

Я пытаюсь реализовать базовую связь через сокеты, теперь у меня есть:

  • запуск сервера для прослушивания на сокете,

    this.serverSocket_ = new ServerSocket(this.serverPort_);
    clientSocket = this.serverSocket_.accept();
    
  • клиент подключается, и сервер запускает отдельный поток для работы с этим клиентом,

  • и открытые потоки вывода и ввода объекта,

    out = new ObjectOutputStream(clientSocket_.getOutputStream());
    out.flush();
    in = new ObjectInputStream(clientSocket_.getInputStream());
    
  • клиент отправляет два i Double, String и Long по этому потоку (сбрасывает после каждого),

        out.writeObject(conf_);
        out.flush();
        out.writeObject(supp_);
        out.flush();
        out.writeObject(separator_);
        out.flush();
        out.writeObject(new Long(dataFile_.length()));
        out.flush();
    
  • сервер успешно получает эти объекты через ранее открытые потоки,

    conf_ = (Double) in_.readObject();
    supp_ = (Double) in_.readObject();
    separator_ = (String) in_.readObject();
    fileSize_ = (Long) in_.readObject();
    
  • и теперь «трудная часть»,

  • клиенты хотят отправить файл, поэтому открывает другой выходной поток (не выходной поток объекта) иотправляет файл,

    FileInputStream fis = new FileInputStream(dataFile_);
    BufferedInputStream bis = new BufferedInputStream(fis);
    OutputStream os = clientSocket_.getOutputStream();
    
    while (current < fileSize) {
        bytesRead = bis.read(mybytearray, 0, mybytearray.length);
        if (bytesRead >= 0) {
            os.write(mybytearray, 0, mybytearray.length);
            current += bytesRead;
        }
        progressBar_.setValue(current);
        progressBar_.repaint();
    }
    os.flush();
    
  • сервер получает файл (вместо ObjectInputStream также используется простой поток ввода),

    int bytesRead;
    int current = 0;
    
    tmpFile_ = File.createTempFile("BasketAnalysis", "rec.dat");
    
    byte[] mybytearray = new byte[fileSize];
    InputStream is = clientSocket_.getInputStream();
    FileOutputStream fos = new FileOutputStream(tmpFile_);
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bytesRead = is.read(mybytearray, 0, mybytearray.length);
    current = bytesRead;
    
    do {
        bytesRead = is.read(mybytearray, current,
        (mybytearray.length - current));
        if (bytesRead >= 0)
            current += bytesRead;
    
    } while ((bytesRead > -1) && (current < fileSize));
    
    bos.write(mybytearray, 0, current);
    bos.flush();
    bos.close();
    
  • такдалеко все работает нормально, файл получен, но теперь сервер выполняет на этом сервере много временипосле чего отправляет ответ с результатами клиента,

    String resp = new String("Some processing result...");
    out_.writeObject(resp);
    out_.flush();
    
  • клиент должен получить результат, который завершает все сообщение,

    String message = (String) in.readObject();
    Console.info("server > " + message);
    

К сожалению, последний шаг на стороне клиента завершается с ошибкой:

    java.io.EOFException
        at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
        at java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.io.ObjectInputStream.readObject(Unknown Source)
        at basketAnalysis.client.Client.run(Client.java:74)
        at java.lang.Thread.run(Unknown Source)

Я хочу, чтобы клиент блокировал ожидание ответа сервера после отправки файла, но после отправки он неожиданно завершает работу с исключением.файл.Я совершенно уверен, что я делаю что-то не так с переключением между простыми потоками и потоками объектов.

Кто-нибудь знает, что я должен изменить, чтобы он работал?

Заранее спасибо!

1 Ответ

3 голосов
/ 30 октября 2011

Я думаю, что ваше основное недоразумение здесь:

клиенты хотят отправить файл, поэтому открывается другой поток вывода

OutputStream os = clientSocket_.getOutputStream();

Это не открывает другой выходной поток - он получит другую ссылку на тот же выходной поток, который вы уже заключили в ObjectOutputStream. Если вам нужны два потока данных, вам нужно открыть два отдельных соединения.

...