2016-01-21 97 views
0

我一直在使用TCP服務器/客戶端的東西一段時間。當涉及到連接多個多客戶端用戶時,我非常擅長UDP編程。我試圖做同樣的,我把使用線程但每當線程獲取到這段代碼使用線程處理多個Java TCP客戶端

String reader = (String)in.readObject(); 

產生一個錯誤,並且線程停止執行的代碼,但該線程仍然運行該程序的TCP服務器上保持活力。 反正這裏是完整的源代碼:

public class TestServer implements Runnable { 

private Thread run, streams, connect, receive, send; 

private ServerSocket socket; 
private Socket conn; 
private ObjectInputStream in; 
private ObjectOutputStream out; 

private boolean running, incomingMessage = false; 
private int port; 

public TestServer(int port) throws IOException { 

    this.port = port; 

    socket = new ServerSocket(port); 

    console("Server stated on : " + InetAddress.getLocalHost() + " : " + port); 

    run = new Thread(this, "Run"); 
    run.start(); 

} 

public void run() { 

    running = true; 
    connect(); 
    receive(); 
} 

private void connect() { 

    connect = new Thread("Connect") { 

     public void run() { 

      while(running) { 

       try { 
        conn = socket.accept(); 
       } catch (IOException e) { 

        e.printStackTrace(); 
       } 

       console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort()); 

       try { 
        setupStreams(); 
       } catch (IOException e) { 

        e.printStackTrace(); 
       } 

      } 


     } 

    }; connect.start(); 

} 

private void setupStreams() throws IOException { 

    streams = new Thread("Streams") { 

     public void run() { 

      try { 

       console("Setting up Streams"); 

       out = new ObjectOutputStream(conn.getOutputStream()); 
       out.flush(); 

       in = new ObjectInputStream(conn.getInputStream()); 

       console("Streams are now setup"); 

       incomingMessage = true; 
       receive.start(); 

      } catch(IOException e) { 
       e.printStackTrace(); 
      } 
     } 

    }; streams.start(); 



} 

private void receive() { 

    receive = new Thread("Receive") { 

     public void run() { 

      while(incomingMessage) { 

       String message = ""; 

       try { 

        message = (String) in.readObject(); 
        //This is the only flaw the program 

       } catch (ClassNotFoundException | IOException e) { 

        e.printStackTrace(); 
       } 

       console("Client : " + message); 
      } 
     } 

    }; 
} 

private void console(String message) { 
    System.out.println(message); 
} 

public static void main(String[] args) { 
    try { 
     new TestServer(1234); 
    } catch (IOException e) { 

     e.printStackTrace(); 
    } 
} 

}

FYI不是新的這一點。錯誤是由於服務器開始接收數據包,即使沒有數據包要接收。但是因爲線程強制它接收它,所以我在線程中產生錯誤,並且不知道其他任何方法來解決這個問題。所以請幫助。提前致謝。

+0

'incomingMessage'從未設置從初始到'FALSE'分開,所以while循環無法結束。 –

+0

定義'生成錯誤'。 – EJP

回答

0

每個連接不應該需要2個線程。一個線程是所有必需的。連接被接受後,將其傳遞給工作線程開始閱讀。這可以在工作線程的while循環中完成。

即使可以讀取套接字的輸入流,ObjectInputStream()類也更爲敏感。如果有任何錯誤,它的狀態會被破壞並且不能被使用。

while (true) { 
     try { 
      Object input = in.readObject(); 
      message = (String) input; 
     } catch (IOException e) { 
      e.printStackTrace(); 
      break; //unrecoverable 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
      break; //unrecoverable 
     } 

     console("Client : " + message); 
    } 

這是一個更好的設計,使用特定的消息協議,而不是發送序列化的Java對象。例如,如果您要像您的示例一樣發送字符串,則可以使用InputStreamReader將字節更容易地轉換爲字符,並且處理更少的錯誤。

這些資源將有助於您:

https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later

Java - Listening to a socket with ObjectInputStream

ObjectInputStream(socket.getInputStream()); does not work

+0

感謝兄弟,至少我現在有一個起點。 – Neokon

+0

讀取循環不正確。 'readObject()'在流結束時不返回null:它拋出一個'EOFException.'。Null可以發生在流的任何地方,不應該被當作終止標記。 – EJP

+0

@EJP你是對的。我回顧了Java源代碼。看起來你必須閱讀,直到一個例外... –