Потоки — ObjectOutputStream дает NULL

У меня есть два приложения, которые работают вместе. Одним из них является приложение типа «сервер», которое не имеет графического интерфейса и обрабатывает запросы к базе данных и обрабатывает запросы от клиента. Другой - это «клиент», который в основном представляет собой графический интерфейс и предназначен для пользователей, чтобы взаимодействовать с информацией базы данных структурированным образом.

ПРОБЛЕМА / ПРОБЛЕМА / НЕОБХОДИМА ПОМОЩЬ

Проблема, с которой я сталкиваюсь, заключается в том, что я могу успешно и без проблем отправить один объект (String []) на сервер. Клиентское приложение отправляет его, серверное приложение получает и успешно обрабатывает.

Если я попытаюсь отправить вторую строку [], клиент компилирует массив и думает, что он отправлен, но сервер никогда не получает его (получает только null) и создает исключение IOException.

Это даже с массивами, которые содержат одинаковое количество позиций и один и тот же текст в точно таком же формате и позициях.

Ошибка, создаваемая printStackTrace():

Java.io.OptionalDataException
at java.io.ObjectInputStream.readObject0 (ObjectInputStream.java:1367)
at java.io.ObjectInputStream.readObject (ObjectInputStream.java:369)
at server.ConnectionThread.processClientRequests(ConnectionThread:204)
at server.ConnectionThread.processClientRequests(ConnectionThread:50)
at javalang.Thread.run(Thread.java:722) 

Код в строке 204, которая является точкой, из которой считывается ObjectStream:

String[] addArray = (String[]) ois.readObject();

ois является ObjectInputStream и инициализируется следующим образом:

private ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

КЛИЕНТСКИЙ КОД

Код клиента, используемый для отправки этих объектов серверному приложению:

ObjectToServer.writeObject(String[] var);
ObjectToServer.flush();
ObjectToServer.reset();

КОММЕНТАРИИ

Что для меня НЕ имеет смысла, так это то, что этот точно такой же формат кода используется для успешной отправки числа String[] через objectOutputStream с СЕРВЕРА в приложение CLIENT без отправки «нулевого» значения.

Я искал это в Google, и все безрезультатно.

Кто-нибудь, пожалуйста, помогите, если можете!!

                             ADDITIONAL CODE

// CONNECTION THREAD IS ON SERVER APP, SETS UP STREAMS AND WAITS FOR MESSAGES FROM CLIENT
// HANDLES COMMUNICATION FROM CLIENT AND REST OF SERVER

public class ConnectionThread implements Runnable
{

    private Socket socket;
    private SystemCore core;
    //Streams for connections
    private InputStream is;
    private OutputStream os;
    //Writers and readers for communication of Strings
    private PrintWriter toClient;
    private BufferedReader fromClient;
    // Writers and readers for sending and receiving Objects between server and client.
    private ObjectInputStream ois = null;
    private ObjectOutputStream oos = null;
    //Protocol
    static final String CLIENT_QUITTING = "Exit";

    public ConnectionThread(Socket s, SystemCore aSysCore)
    {
        socket = s;

        // State of the SystemCore as taken from HelloServer
        core = aSysCore;
    }

    public void run()
    {
        try
        {
            openStreams();
            toClient.println(MESSAGE_TO_CLIENT);
            processClientRequests();
            closeStreams();
            this.socket.close();
        }
        catch (OptionalDataException ode )
        {
            System.out.println("OptionalDataException: ");
            System.out.println("length is: " + ode.length);
        }
        catch (IOException ioe)
        {
            System.out.println("IO trouble with a connection in ConnectionThread run() " + ioe.getMessage());
            ioe.printStackTrace();
        }
       catch (ClassNotFoundException cnf)
        {
            System.out.println("Class trouble with a connection in ConnectionThread run() " + cnf.getMessage());
            cnf.printStackTrace();
        }
        catch(ParseException pe)
        {
            System.out.println("Parse trouble with a connection in ConnectionThread run() " + pe.getMessage());
            pe.printStackTrace();
        } 
    }

    /**
     * Opens streams between the server and the client.
     *
     * @throws IOException
     */
    private void openStreams() throws IOException
    {
        final boolean AUTO_FLUSH = true;
        this.is = this.socket.getInputStream();
        this.fromClient = new BufferedReader(new InputStreamReader(is));
        this.os = this.socket.getOutputStream();
        this.toClient = new PrintWriter(os, AUTO_FLUSH);

        //Object streams.
        oos = new ObjectOutputStream(socket.getOutputStream());
        ois = new ObjectInputStream(socket.getInputStream());

        System.out.println("...Streams set up");
    }


    /**
     * Private method that accepts arguments from a client and executes the related
     * commands in the systemcore as long as the command passed from the client
     * is not CLIENT_QUITTING.
     *
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void processClientRequests() throws IOException, ClassNotFoundException, ParseException
    {
        String commandFromClient;
        commandFromClient = fromClient.readLine();
        while (!(commandFromClient.equals(CLIENT_QUITTING)))
        {
            if (commandFromClient.equals("addProjectPrepare"))
            {
                String[] addArray = (String[]) ois.readObject();
                core.addProjectPrepare(addArray);
            }
            if (commandFromClient.equals("editProjectPrepareDetails"))
            {
                String[] editArray = (String[]) ois.readObject();
                recruit.editProjectPrepareDetails(editArray);               
            }
        }
           commandFromClient = fromClient.readLine();
    }


**// CLIENT SIDE (User GUI) CODE THAT SENDS STRING[] TO THE SERVER**




public void saveAction()
    {
        // TEST TO SEE IF THE DATE ENTERED IS CORRECT FORMAT, IF NOT NO SAVE OCCURRS

    boolean parsedOk = false;

    if (this.arrivalDateTextField.getText().isEmpty() == false)
    {
        try
        {
            // Check if date is correct format. Nothing will be done with 
            // the testDate object

            MyDate testDate = new MyDate(
                    this.arrivalDateTextField.getText());

            //Allow write to server to occur.
            parsedOk = true;
            //If date is okay, send form data to server.
        }
        catch (ParseException pe)
        {
            this.arrivalDateTextField.setText(""); // Set text field to blank
            int messageIcon = javax.swing.JOptionPane.ERROR_MESSAGE;
            JOptionPane.showMessageDialog(this, "Invalid date",
                    "Warning", messageIcon);
        }
    }
    else
    {
        parsedOk = true; // No date entered so allow blank. 
    }
    if (parsedOk == true)
    {
        // WRITE DATA TO SERVER OCCURS HERE: 

        try
        {

            **//getPersonDetails() returns a String[]**

            ManageClientConnections.toServer.println("addNewData");                 
       ManageClientConnections.objectToServer.writeObject(this.getPersonDetails());
            ManageClientConnections.objectToServer.flush();
            ManageClientConnections.objectToServer.reset();
        }
        catch (IOException ioe)
        {
            System.out.println(
                    "While writing new person to server, there was an error: " + ioe.getMessage());
        }

        // And dispose of the GUI, inside the parseok if clause
        this.dispose();
    }
}

person JTB    schedule 19.02.2013    source источник
comment
Можете ли вы поймать OptionalDataException и распечатать поле exception.length, пожалуйста? Кроме того, комментарий выше.   -  person ddmps    schedule 19.02.2013
comment
Почему вы сбрасываете выходной поток?   -  person Fildor    schedule 19.02.2013
comment
Спасибо Pescis и jtahlborn - я добавил применимый дополнительный код. @Pecsis — в exception.length для OptionalDataException длина равна 0. Fildor — я сбрасываю выходной поток, потому что у меня есть один открытый поток, и я снова и снова записываю в него объекты. Согласно тому, что я читал (некоторое время назад), мне нужно сбросить ObjectOutputStream, иначе будут постоянные ошибки.   -  person JTB    schedule 19.02.2013
comment
сервер никогда не получает is (получает только null) и создает исключение IOException. Нет. Он выдает IOException вместо создания чего-либо. Любые нули создаются вашим кодом.   -  person user207421    schedule 20.02.2013
comment
@Fildor Если вы не знаете, что делает ObjectOutputStream.reset(), посмотрите. Для ОП здесь нет ничего странного.   -  person user207421    schedule 20.02.2013
comment
@EJP: я знаю, что он делает. Я хотел знать, есть ли у ОП особая причина для этого.   -  person Fildor    schedule 20.02.2013


Ответы (1)


Вы не можете создавать несколько потоков ввода/вывода поверх одних и тех же потоков ввода/вывода сокета. это не работает. вам нужно выбрать один тип потока и придерживаться его. Поскольку вам нужно отправлять структурированные данные, вы должны использовать только потоки объектов и исключить потоки печати. если вам нужно отправлять различные типы сообщений от клиента к серверу, вам следует рассмотреть возможность использования оберточного типа объекта Serializable (например, Message), который может содержать различные типы сообщений.

person jtahlborn    schedule 19.02.2013
comment
Но это один поток с несколькими objects, записанными в него, а затем очищенными и сброшенными, а не несколькими streams. И запись нескольких объектов в один поток из серверного приложения в клиентское приложение работает. - person JTB; 19.02.2013
comment
@joelBeaton - а? ваш метод openStreams создает BufferedReader и ObjectInputStream поверх того же сокета InputStream. - person jtahlborn; 19.02.2013
comment
Правда, один из них (BufferedReader) обрабатывает строки, записанные в него PrintWriter в клиентском приложении, а другой (ObjectInputStream) обрабатывает входящие объекты от клиента. Разве это не разрешено? Должен ли я создать два объекта сокета и разделить этот трафик? - person JTB; 19.02.2013
comment
@joelBeaton - ответил на все эти вопросы уже в моем ответе. - person jtahlborn; 19.02.2013
comment
Хорошо, я все исправлю и вернусь к этому, чтобы вы знали, как все прошло. - person JTB; 19.02.2013