【问题标题】:Java: client-sever app.- WHILE on ObjectInputStream read threadJava:客户端-服务器应用程序。-在 ObjectInputStream 读取线程上
【发布时间】:2011-11-03 15:01:00
【问题描述】:

这一定很容易,但我显然缺少一些基本的理解。 我有简单的客户端服务器应用程序

服务器:

public class GameServer{
   private Socket clientSocket;
   private ServerSocket serverSocket;
   private ArrayList<ObjectOutputStream> oosPlayers=new ArrayList<ObjectOutputStream>();   

   public static void main(String args[]){
       GameServer server = new GameServer();
       server.startGame();
   }   

   public void startGame(){  
      try{
         serverSocket = new ServerSocket(10008);  
         System.out.println("Server started at:" + serverSocket);
         while(true){
             System.out.println("Server: Waiting for client requests...");
             clientSocket=serverSocket.accept();
             System.out.println("Server: Client connection accepted at:"+clientSocket);
             //remember player's output stream
             oosPlayers.add(new ObjectOutputStream(clientSocket.getOutputStream()));
             //read data from clients 
             Thread receiverThread = new Thread(new DataReceiver());
             receiverThread.start();
         }
      }
      catch(IOException ex){
          System.out.println(ex.getMessage());
      }
   }
   public class DataReceiver implements Runnable{
       public void run(){
           try{
               String mess;
               ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
               while((mess=(String)ois.readObject()) != null){                         
                   System.out.println("Server: "+mess);
                   send();
               }
           }
           catch(Exception ex){ System.out.println(ex.getMessage()); }
       }
       public void send(){
           for (ObjectOutputStream oos : oosPlayers){
               try{
                   oos.writeObject(new String("There is "+oosPlayers.size()+" player(s) at the board"));                   
                   oos.flush();
               }
               catch(Exception ex){ System.out.println(ex.getMessage()); }  
           }
       }
   }        
}

客户:

public class GameClient implements ActionListener{
   private Socket socket;
   private ObjectInputStream  ois;
   private ObjectOutputStream oos;
   private JButton button;

   public static void main(String args[]){
       GameClient client = new GameClient();  
       client.drawBoard();
   }
   public void drawBoard(){
       JFrame frame = new JFrame("A game");
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       button = new JButton("Send");
       button.addActionListener(this);
       configureConnection();
       Thread receiverThread = new Thread(new DataReceiver());
       receiverThread.start();

       frame.getContentPane().add(new JPanel().add(button));
       frame.setSize(200,200);
       frame.setVisible(true);
   }   
   public void configureConnection(){
       try{
           socket = new Socket("127.0.0.1", 10008);
           ois = new ObjectInputStream(socket.getInputStream());
           oos = new ObjectOutputStream(socket.getOutputStream());
       }
       catch(Exception ex) { System.out.println(ex.getMessage()); }
   }   

   public void actionPerformed(ActionEvent ev){
       if (ev.getSource()==button){
          try{
              oos.writeObject(new String("Some data from client"));
              oos.flush();
          }
          catch(Exception ex){ System.out.println(ex.getMessage()); }         
       }
   }   

   public class DataReceiver implements Runnable{
       public void run(){
           try{
               String mess;
               while((mess=(String)ois.readObject())!= null){                  
                   System.out.println("Client:"+mess);
               }
           }
           catch(Exception ex){ System.out.println(ex.getMessage()); }
       }
   }   
}

我的问题与双方的 receiverThread 有关。当我在从 ObjectInputStream (在 RUN 方法中)读取期间使用 WHILE 时,服务器会侦听客户端请求并将它们正确分派到所有 ObjectOutputStream s。如果我将此 WHILE 更改为 IF,则每个客户端仅从服务器读取(并发送)一次数据。这同样适用于客户端的 WHILE/IF。

我的理解是,当我运行 receiverThread 时,它会以某种方式在 WHILE 停止线程并继续从输入流中读取,而使用 IF 让线程完成(从而停止读取过程)。尽管 WHILE 条件不满足,即最初(还没有客户端连接)它保持 receiverThread 活着,这怎么可能呢?在receiverThread 已经读取数据并且流中没有任何内容之后也会发生同样的情况。

希望能对这个基本问题做出一些解释。

问候 马辛

【问题讨论】:

    标签: java multithreading objectinputstream


    【解决方案1】:

    如果您在 run() 方法中将 while 更改为 if,您只会读取一个对象并退出。如果您的客户端-服务器协议非常简单,例如他们每个会话只发送一个对象,两个版本是相等的。否则系统将无法正常运行:所有其他对象都不会到达。

    【讨论】:

    • 感谢您的回答。我仍然很好奇while((mess=(String)ois.readObject())!= null) 第一次在服务器上执行时,条件失败(流为空),但它没有退出运行方法并继续侦听输入流,这怎么可能。
    • 它不会一直监听 InputStream。它正在监听 socket 因为你还没有关闭它。清晰的实现应该用 try/finally 块包裹 while 循环,并在 finally 块中关闭流。
    • 这可能不正确,但我相信它不会退出while((mess=(String)ois.readObject())!= null),因为您的套接字处于阻塞模式,读取线程将阻塞readObject() 方法,直到它读取数据或套接字关闭(这会导致抛出异常)。
    • 好吧,从字面上看,我会将其读作“当有一些东西要从输入流中读取时(因为套接字仍然打开)做某事”,但这意味着“如果没有任何东西剩下,离开循环”。根据您的建议,这应该被解释为“当套接字处于阻塞模式时,继续读取它”,而使用 IF 这将是“如果套接字处于阻塞模式,则从中读取”。也许这里的混乱座位,但目前我对这个解释很满意,并会假设它是这样的:) 谢谢
    • 离题:有什么方法可以让我欣赏这些答案
    猜你喜欢
    • 2015-09-17
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-02
    • 1970-01-01
    相关资源
    最近更新 更多