2012-03-17 32 views
0

我有一個帶有兩個以上按鈕的客戶端/服務器程序。當點擊一個按鈕時,它會向服務器發送一定的請求。根據請求,服務器必須返回一個字符串數組。我在服務器端使用ObjectOutputStream,在客戶端使用ObjectInputStream。問題是ObjectInputStream不允許我多次調用readObject()方法。是否有更好的方式通過套接字連接發送數組。我使用PrintWriter將請求發送到服務器。我的服務器是多線程的。在多線程服務器中使用ObjectOutputStream發送數組

客戶:

public FuncListener2() 
    { 

     butCheckOutSearchTitle.setEnabled(false); 
     String hostName = ""; 

     try { 
      hostName = InetAddress.getLocalHost().toString(); // to get the hostName for the exceptions 
      clientSocket = new Socket(InetAddress.getLocalHost(), 1211); 
      System.out.println(clientSocket.isConnected()); 
      printWriter = new PrintStream(clientSocket.getOutputStream()); 
      objIn = new ObjectInputStream(clientSocket.getInputStream()); 


      listeners(); 

      clientSocket.setKeepAlive(true); 
     } 
     catch (UnknownHostException e) 
     { 
      System.err.println("Don't know about host "+hostName); 
      e.printStackTrace(); 
     } 
     catch (IOException e) 
     { 
      System.err.println("Couldn't get I/O for the connection to the host "+hostName); 
      e.printStackTrace(); 
     } 
     catch(Exception ex) 
     { 
      System.err.println(ex.getMessage()); 
     } 
    } 

    public void listeners() 
    { 
     System.out.println("in listener"); 

     butCheckOutSearchSurname.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       try 
       { 

        System.out.println("surname search"); 
        int count = 0; 

        String [] array = null; 

        // the reason for the plus sign is to make sure the correct if statement is executed in the server 
        String query = "Select+ * FROM clientDet WHERE clientSurname = \'" + textCheckOutSearchSurname.getText() + "\'"; 
        printWriter.println(query); 

        obj = objIn.readObject(); 

        if(obj != null) 
        { 
         array = (String[])obj; 
        } 
        else 
        { 
         System.out.println("object empty"); 
        } 

        listCheckOutClients.setListData(array); 


       } 
       catch(Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
     }); 

     listCheckOutClients.addListSelectionListener(new ListSelectionListener() 
     { 
      public void valueChanged(ListSelectionEvent e) 
      { 
       try 
       { 
        butCheckOutSearchTitle.setEnabled(true); 


       } 
       catch(Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
     }); 


     butCheckOutSearchTitle.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       try 
       { 

        listCheckOutAvaliable.removeAll(); 
        String [] stringArray = null; 

        // the reason for the plus sign is to make sure the correct if statement is executed in the server 
        String query = "Select- * FROM stock WHERE stockTitle = \'" + textCheckOutSearchTitle.getText() + ",\' AND (stockStatus = \'available\' OR \'reserved\')"; 
        printWriter.println(query); 

        obj = objIn.readObject(); 

        stringArray = (String[])obj; 

        listCheckOutAvaliable.setListData(stringArray); 

        objIn = null; 


       } 
       catch(Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
     }); 
     } 

服務器:

public void run() 
    { 
     try 
     { 
      Class.forName("com.mysql.jdbc.Driver"); 
      conn = DriverManager.getConnection("jdbc:mysql://localhost/videostore", "root", "IronFire"); 

     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
     } 
     try 
     { 
      System.out.println("Server"); 
      in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
      out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream())); 

      objOut= new ObjectOutputStream(clientSocket.getOutputStream()); 

      while (running) 
      { 
       //SELECT+ searching surname 
       //SELECT- searching titles 
       //[email protected] searching ####Num column 



       String command = in.readLine(); 
       System.out.println("Query: " + command); 
       if(command.substring(0, command.indexOf(" ")).equalsIgnoreCase("SELECT+")) 
       { 
        System.out.println("IN IF +"); // for test 
        surname(command); 
       } 
       if(command.substring(0, command.indexOf(" ")).equalsIgnoreCase("SELECT-")) 
       { 
        System.out.println("IN IF -"); // for test 
        title(command); 
       } 
       if (command.equalsIgnoreCase("quit")) 
       { 
        running = false; 
        System.out.print("Stopping client thread for client : " + clientID); 
       } 
       else 
       { 
        out.println(command); 
        out.flush(); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
    public void surname(String query) 

    { 
     try 
     { 
      System.out.println("In Surname"); // for test 
      int count = 0; 
      int whileCounter = 0; 
      Statement state = conn.createStatement(); 

      res = state.executeQuery(query.replace("+", "")); 

      while(res.next()) 
      { 
       count++; 
      } 
      String [] stringResult = new String[count]; 
      res.beforeFirst(); 

      while(res.next()) 
      { 
       stringResult[whileCounter] = res.getString(1) +" "+ res.getString(2) +" " + res.getString(3) +" "+ res.getString(5) +" "+ res.getString(10) +" "+ res.getString(11) +""; 
       whileCounter++; 
      } 


      objOut.reset(); 
      objOut.writeUnshared(stringResult); 
      objOut.flush(); 



     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
     } 

    } 
    public void title(String query) 
    { 
     try 
     { 
      int count = 0; 
      int whileCounter = 0; 

      Statement state = conn.createStatement(); 

      res = state.executeQuery(query.replace("-", "")); 
      System.out.println(query.replace("-", "")); 

      while(res.next()) 
      { 
       count++; 
      } 
      System.out.println(count); 
      String [] stringResult = new String[count]; 

      res.beforeFirst(); 

      while(res.next()) 
      { 
       stringResult[whileCounter] = res.getString(1) +" "+ res.getString(2) +" " + res.getString(3) +" "+ res.getString(5) +""; 
       whileCounter++; 
      } 

      for(int a = 0; a< stringResult.length; a++) 
      { 
       System.out.println(stringResult[a]); 
      } 

      objOut.reset(); 
      objOut.writeUnshared(stringResult); 
      objOut.flush(); 

     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
     } 
    } 

} 

的錯誤,這是唯一的錯誤,這是在客戶端:

java.io.StreamCorruptedException: invalid type code: 53 
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1374) 
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369) 
    at FuncListener2$3.actionPerformed(FuncListener2.java:197) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 
    at java.awt.Component.processMouseEvent(Component.java:6505) 
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) 
    at java.awt.Component.processEvent(Component.java:6270) 
    at java.awt.Container.processEvent(Container.java:2229) 
    at java.awt.Component.dispatchEventImpl(Component.java:4861) 
    at java.awt.Container.dispatchEventImpl(Container.java:2287) 
    at java.awt.Component.dispatchEvent(Component.java:4687) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832) 
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492) 
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422) 
    at java.awt.Container.dispatchEventImpl(Container.java:2273) 
    at java.awt.Window.dispatchEventImpl(Window.java:2713) 
    at java.awt.Component.dispatchEvent(Component.java:4687) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707) 
    at java.awt.EventQueue.access$000(EventQueue.java:101) 
    at java.awt.EventQueue$3.run(EventQueue.java:666) 
    at java.awt.EventQueue$3.run(EventQueue.java:664) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) 
    at java.awt.EventQueue$4.run(EventQueue.java:680) 
    at java.awt.EventQueue$4.run(EventQueue.java:678) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) 

回答

0

你可以調用的readObject( )可以隨意多次。問題可能在於沒有什麼可讀的時候它會阻止。你可以讓這個閱讀器使用後臺線程,所以它的阻塞並不重要。

ObjectOutputStream假定對象是不可變的。如果更改一個對象,它不會再發送一次,而是發送一個對該對象的引用。

如果您希望每次在調用之間使用writeUnshared()或使用reset()時發送一個對象的新副本。


ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(baos); 

List<String> strings = new ArrayList<String>(); 
strings.add("hello"); 

oos.writeUnshared(strings); 

strings.set(0, "world"); 

oos.writeUnshared(strings); 

oos.close(); 

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); 

System.out.println(ois.readObject()); 
System.out.println(ois.readObject()); 

打印

[hello] 
[world] 
+0

我的程序工作的方式是,我必須按下一個按鈕獲取數組使用JList選擇數組。那將啓用另一個按鈕。當我按下請求發送的按鈕。但在我看來,服務器發送回客戶端的數組與第一個數組衝突。 – IronFire 2012-03-17 14:22:27

+0

我假設你正在改變你已經發送並重新發送的數組,但是你看到原始的兩次?看我的編輯。 – 2012-03-17 14:25:30

+0

我嘗試使用writeUnshared(),但它給了我一個StreamCorruptedException。 – IronFire 2012-03-17 15:54:31

0
out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream())); 

objOut= new ObjectOutputStream(clientSocket.getOutputStream()); 

您在插座上註冊多個輸出流,一些流可以使用緩衝,其他人可能得到儘可能多的字節有,或者在你不知道的情況下發送字節,導致接收端接收到正確順序的字節,確保你沒有得到se bugs,總是隻在套接字上註冊1個輸出流,而不是更多。