ObjectInputStream в цикле while - PullRequest
       38

ObjectInputStream в цикле while

0 голосов
/ 02 апреля 2020

У меня есть проект java, где у меня должен быть клиент и сервер. Клиент отправляет объект на сервер, который сохраняет его в векторе, в основном, среди других задач. Моя проблема в том, что я продолжаю получать исключение EOF во время работы. Вот мой код сервера:

import java.net.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;

public class Server extends JFrame {
  //Attributes
  private Vector<Sales> allSales;
  private int counter;
  //Constructor
  public Server() {
    counter = 0;
    setLayout(new BorderLayout());
    allSales = new Vector<Sales>();
    try {
     InetAddress inetAddress = InetAddress.getLocalHost();
     JLabel ip = new JLabel("IP Address of server: " + inetAddress.getHostAddress());
     add(ip, BorderLayout.NORTH);
    }
    catch(UnknownHostException uhe) {
     uhe.printStackTrace();
    }

    JButton jbWrite = new JButton("Write to CSV");
    add(jbWrite, BorderLayout.SOUTH);

    ActionListener writeListener = new ActionListener() {
      public void actionPerformed(ActionEvent ae) {
        writeFilesToCSV();
      }
    };

    //Window Listener that writes final files to csv on exit
    addWindowListener(new WindowAdapter() {
      public void actionPerformed(ActionEvent ae) {
        writeFilesToCSV();
        System.exit(0);
     }
    }); 

    //Finalize GUI
    setTitle("Server");
    setSize(400,400);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    //Internet stuff
    try {
      ServerSocket ss = new ServerSocket(16789);
      Socket cs = null;
      while(true) {
        cs = ss.accept();
        ThreadServer ths = new ThreadServer(cs);
        ths.start();
     }
   }
   catch(BindException be) {
     System.out.println("Server already running");
   }
   catch(IOException ioe) {
     ioe.printStackTrace();
   }
 }

 //ThreadServer class
 class ThreadServer extends Thread {
   Socket cs;

   public ThreadServer(Socket _cs) {
     cs = _cs;
   }

   public void run() {
     ObjectInputStream ois = null;
     ObjectOutputStream oos = null;
     try {
        ois = new ObjectInputStream(new FileInputStream("file.dat"));
        oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
     }
     catch(IOException ioe) {ioe.printStackTrace(); }
     while (true) {
        try {
           Object inOB = ois.readObject();
           if(inOB instanceof String) {
              String command = (String)inOB;
              if(command.equalsIgnoreCase("count")) {
                 oos.writeObject(counter);
                 oos.flush();
              }
              if(command.equalsIgnoreCase("exit")) {
                 cs.close();
                 break;
              }
           }
           else if(inOB instanceof Sales) {
              synchronized(this) {
                 Sales saleToRecord = (Sales)inOB;
                 allSales.add(saleToRecord);
                 counter++;
              }
           }
        }
        catch(EOFException eofe) {
           eofe.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
           cnfe.printStackTrace();
        }
        catch(IOException ioe) {
           ioe.printStackTrace();
        }
     }
  }
}
//Other Methods
public void writeFilesToCSV() {
  synchronized(this) {
     try {
        File outFile = new File("Sales.csv");
        FileWriter writer = new FileWriter(outFile, true);
        for(Sales s : allSales) {
           writer.write(s.getName() + "," + s.getNum() + "," + s.getItemNum() +"\n");
           writer.flush();
        }
        allSales.clear();
        writer.close();
     }
     catch(IOException ioe) {
        ioe.printStackTrace();
     }
  }
}

 //Main
 public static void main(String[] args) {
   new Server();
 }
}

Итак, я знаю, что ошибка происходит в операторе run() потока. У меня есть

while(true) {
  Object inOB = ois.readObject();
  .....
}

Это, очевидно, вызывает исключение EOF, потому что он пытается прочитать файл, в котором нет информации, file.dat. В этот файл клиент отправляет информацию, когда вводит информацию в GUI. Я пытаюсь выяснить, как заставить код ждать, пока объект будет отправлен, а затем выполнить, или, я думаю, просто не создавать бесконечное количество ошибок.

Код клиента (при необходимости)

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class Client extends JFrame {
   //Attributes
   private JTextField jtfSP;
   private JTextField jtfCN;
   private JTextField jtfIN;
   private ObjectOutputStream oos;
   private ObjectInputStream ois;
   private Sales outOB;
   private Socket s;

   //Constructors
   public Client() {
      //Create GUI for sales
      //It should have a box to record Sales persons name, customer number, and item number of object sold
      setLayout(new BorderLayout());
      JPanel jpCenter = new JPanel();
      GridLayout grid = new GridLayout(3,2);
      jpCenter.setLayout(grid);
      JLabel sp = new JLabel("Salesperson:");   //JLabel salesperson
      jpCenter.add(sp);
      jtfSP = new JTextField(); //text field salesperson
      jpCenter.add(jtfSP);
      JLabel cn = new JLabel("Customer number:"); //label cust num
      jpCenter.add(cn);
      jtfCN = new JTextField(); //text field cust num
      jpCenter.add(jtfCN);
      JLabel in = new JLabel("Item number:"); //label item num
      jpCenter.add(in);
      jtfIN = new JTextField(); //text field item num
      jpCenter.add(jtfIN);
      add(jpCenter, BorderLayout.CENTER);

      //Record, Count, Exit Buttons
      JPanel jpSouth = new JPanel();
      GridLayout southGrid = new GridLayout(1,3);
      jpSouth.setLayout(southGrid);
      JButton jbRec = new JButton("RECORD");
      jpSouth.add(jbRec);
      JButton jbCount = new JButton("COUNT");
      jpSouth.add(jbCount);
      JButton jbExit = new JButton("EXIT");
      jpSouth.add(jbExit);
      add(jpSouth, BorderLayout.SOUTH);


      //Create objectinput and output streams
      try {
         ois = new ObjectInputStream(new FileInputStream("file.dat"));
         oos = new ObjectOutputStream(new FileOutputStream("file.dat"));
      }
      catch(IOException ioe) {ioe.printStackTrace(); }
      //ActionListeners

      /*
       *recordListener
         Listens if the record button is clicked
         If it is, it sends record command to server
         creates sale object
         writes object to output
       */
      ActionListener recordListener = new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            //Sends object info
               try {
               String salesName = jtfSP.getText();
               String custNum = jtfCN.getText();
               String itemNum = jtfIN.getText();
               outOB = new Sales(salesName, custNum, itemNum);
               oos.writeObject(outOB);
               oos.flush();

               //Clear fields
               jtfSP.setText(null);
               jtfCN.setText(null);
               jtfIN.setText(null);
            }
            catch(IOException ioe) {
               ioe.printStackTrace();
            }

         }
      };
      jbRec.addActionListener(recordListener);

      /*
       * Count Listener
         Listens to see if count button is clicked
         If it does, it sounds count command to server
         Server returns with amount of objects wrote
       */
      ActionListener countListener = new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            //Returns count of records
            try {
               int count;
               oos.writeObject(new String("count"));
               oos.flush();
               count = (int)ois.readObject();
               JOptionPane.showMessageDialog(null, "Count: " + count);  //displays count
            }
            catch(IOException ioe) {
               ioe.printStackTrace();
            }
            catch(ClassNotFoundException cnfe) { cnfe.printStackTrace(); }
         }
      };
      jbCount.addActionListener(countListener);

      /*
       * exitListener
         Listens to see if exit button is clicked
         If it is it sends exit command to server
         Shuts down exisiting writer
         Exits program
       */
      ActionListener exitListener = new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            //Exits 
            try {
               oos.writeObject(new String("exit"));
               oos.flush();
               ois.close();
               oos.close();
               System.exit(0);
            }
            catch(IOException ioe) {
               ioe.printStackTrace();
            }
         }
      };
      jbExit.addActionListener(exitListener);

      //Final Steps for gui
      setTitle("Sales");
      setSize(400,200);
      setLocationRelativeTo(null);
      //Does same task as exit button, but for the X button/ red dot on mac
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            try {
               oos.writeObject(new String("exit"));
               oos.flush();
               ois.close();
               oos.close();
               System.exit(0);
            }
            catch(IOException ioe) {
               ioe.printStackTrace();
            }
         }
      });
      setVisible(true);

      //Connects to server
      try {
         s = new Socket("localhost", 16789);
      }
      catch(IOException ioe) {
         String message = "Server has shut down or can not be connected to. No more orders will be accepted, the program will exit.";
         JOptionPane.showMessageDialog(null, message);
         System.exit(0);
      } 
   }


   //Other Methods

   //Main
   public static void main(String[] args) {
      new Client();
   }
}
...