2015-02-12 20 views
1

好的,所以我編寫了一個簡單的使用服務器的通信程序,真的比其他任何東西都更像一個測試,所以我知道它很少,但與下面的客戶端類:從套接字聲明輸入/輸出流阻止程序繼續

public class Client { 
    private ObjectInputStream in; 
    private ObjectOutputStream out; 

    private Socket socket; 

    private String server; 
    private int port; 

    public Client(String ip, int p){ 
     port = p; 
     server = ip; 
    } 

    public boolean start(){ 
     try{ 
      socket = new Socket(server, port); 
     }catch(Exception e){ 
      System.out.println("Exception"); 
      e.printStackTrace(); 
      return false; 
     } 
     try{ 
      in = new ObjectInputStream(socket.getInputStream()); 
      out = new ObjectOutputStream(socket.getOutputStream()); 
      System.out.println("All declared"); 
     }catch(Exception e){ 
      System.out.println("Exception"); 
      e.printStackTrace(); 
      return false;} 
     new LThread().start(); 
     return true; 
    } 

    private void sendMessage(Message msg){ 
     try{ 
     out.writeObject(msg); 
     }catch(Exception e){} 
    } 

    public static void main(String[] args){ 
     int portNum = 1500; 
     String servers = "localhost"; 

     Client client = new Client(servers, portNum); 

     System.out.println("Client started"); 

     if(!client.start()){ 
      System.out.println("Didn't work"); 
      return; 
     } 

     System.out.println("Client started again"); 


     Scanner scan = new Scanner(System.in); 

     while(true){ 
      String i = scan.nextLine(); 
      client.sendMessage(new Message(2, i)); 
     } 
    } 

    class LThread extends Thread{ 

     public void run(){ 
      System.out.println("Lthread running"); 
      while(true){ 
       try{ 
        String message = (String)in.readObject(); 
        System.out.println(message); 
       }catch(Exception e){ 
        e.printStackTrace();} 
      } 
     } 

    } 
} 

程序時,它達到它宣稱其ObjectInputOutputStream了問題的實質只是停止。該程序沒有退出,它似乎沒有進入catch區塊,我根本無法弄清楚究竟是什麼導致了它。 「所有聲明」行。從不打印,但是打印之前的任何東西。任何人都可以告訴我爲什麼我的程序在這個時候停止運行而沒有顯示任何錯誤?

編輯:我的身影,有可能在我的服務器文件的地方是一個錯誤,所以這裏的類:

public class Server { 

    private static int uid; 

    private ArrayList<ClientThread> clients; 
    private int port; 
    private boolean cont; 

    public Server(int p){ 
     port = p; 
     clients = new ArrayList<ClientThread>(); 
    } 

    public void start(){ 
     System.out.println("Started"); 
     cont = true; 
     try{ 
      ServerSocket srvr = new ServerSocket(port); 
      System.out.println("Declared socket"); 
      while(cont){ 
       Socket sk = srvr.accept(); 
       System.out.println("Socket accepted"); 

       if(!cont)break; 

       ClientThread t = new ClientThread(sk); 
       clients.add(t); 
       t.start(); 
      } 
      try{ 
       srvr.close(); 
       for(ClientThread t : clients){ 
        t.in.close(); 
        t.out.close(); 
        t.socket.close(); 
       } 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
     }catch(Exception e){ 

      e.printStackTrace(); 
     } 
    } 

    private synchronized void broadcast(String msg){ 
     for(int i=clients.size(); --i >= 0;){ 
      ClientThread t= clients.get(i); 
       if(!t.writeMsg(msg)){ 
        clients.remove(i); 
       } 
     } 
    } 

    public static void main(String[] args){ 
     int portNum = 1500; 

     Server server = new Server(portNum); 
     server.start(); 
    } 

    class ClientThread extends Thread{ 
     Socket socket; 
     ObjectInputStream in; 
     ObjectOutputStream out; 
     String name; 
     int id; 
     Message m; 

     ClientThread(Socket s){ 
      id = ++uid; 
      socket = s; 
      try{ 
       System.out.println("Before"); 
       in = new ObjectInputStream(socket.getInputStream()); 
       out = new ObjectOutputStream(socket.getOutputStream()); 
       System.out.println("After"); 
      }catch(Exception e){ 
       e.printStackTrace();} 
     } 

     public void run(){ 
      boolean c = true; 
      while(c){ 
       try{ 
        m = (Message)in.readObject(); 
        switch(m.getType()){ 
        case 2: 
         broadcast(m.getMessage()); 
        } 
       }catch (Exception e){ 
        e.printStackTrace();} 
      } 
     } 

     public boolean writeMsg(String msg){ 
      if(!socket.isConnected()){ 
       return false; 
      } 
      try{ 
       out.writeObject(msg); 
      }catch(Exception e){ 
       e.printStackTrace();} 
      return true; 
     } 
    } 

} 

好吧,另一個編輯。所以我在ClientThread的構造函數中將這兩個println s添加到try聲明中,就像客戶端一樣,它會運行,直到我嘗試初始化流,然後它停止。再次,沒有錯誤,沒有任何東西;它完全停止在它的軌道上。我無法弄清楚爲什麼發生這種情況,但如果它意味着什麼,我使用Eclipse IDE來運行它。

+0

只是一個提示:打印「所有聲明」之上的兩行不聲明任何東西。 – immibis 2015-02-12 02:36:30

+0

你怎麼知道它沒有卡在'新的套接字(服務器,端口)'? – immibis 2015-02-12 02:37:50

+0

@immibis正確,但將輸出更改爲「All assigned。」。不會真的讓代碼運行得更好。 – user2649681 2015-02-12 02:38:06

回答

1

我在第一次使用時就掛了這個ObjectInputStreamObjectOutputStream。在你的問題的根本原因是在constructor ObjectInputStream。構造函數將從底層流中讀取數據,以嘗試獲取標頭信息,例如有線格式版本。

爲了防止您的客戶端和服務器無限等待其他人先發送信息,您應該顛倒輸入和輸出流的順序,然後明確刷新輸出流。以下在客戶端和服務器中的流構造將解決您的問題:

out = new ObjectOutputStream(socket.getOutputStream()); 
out.flush(); 
in = new ObjectInputStream(socket.getInputStream()); 
out = new ObjectOutputStream(socket.getOutputStream()); 
out.flush(); 
in = new ObjectInputStream(socket.getInputStream());