2012-10-28 95 views
1

我的程序工作正常,許多用戶可以連接並向服務器發送命令。 但是,當用戶使用命令向服務器發送垃圾郵件時,服務器會阻止所有其他客戶端,並且服務器不會從垃圾郵件發送者以外的客戶端接收消息。 這是爲什麼?Java TCP多線程問題

TCPAccept聯繫


package game.server; 

import java.io.IOException; 
import java.net.Socket; 

public class TCPAcceptConnections implements Runnable 
{ 
    public static Socket clientSocket = null;; 
    int clientID = -1; 

    public void run() 
    { 
     while(Main.TCP) 
     { 
      try 
      { 
       clientSocket = TCPServer.serverSocket.accept(); 
       System.out.println("Client Connected."); 
       clientID++; 

       new TCPClientManager(clientSocket, clientID).run(); 
      } 
      catch (IOException e) 
      { 
       System.out.println("Couldn't create client socket."); 
       System.exit(-1); 
      } 
     } 
    } 
} 

TCPClientManager:


package game.server; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.Socket; 

public class TCPClientManager implements Runnable 
{ 
    Socket client; 

    int clientID; 

    static PrintWriter out; 
    static BufferedReader in; 
    String inputLine, outputLine; 

    boolean destroy = false; 

    public TCPClientManager(Socket cs, int id) 
    { 
     try 
     { 
      client = cs; 
      clientID = id; 
      out = new PrintWriter(client.getOutputStream(), true); 
      in = new BufferedReader(new InputStreamReader(client.getInputStream())); 
     } catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void run() 
    { 
     System.out.println("Created TCPManager for client."); 
     String command; 

     while(!destroy) 
     { 
      try 
      { 
       if((command = in.readLine()) != null) //If received something 
       { 
        System.out.println("Commad received: " + command); 
         System.out.println(" " + Commands.proccessCommand(command)); 
        System.out.println("Command proccessed"); 
       } 
       else 
       { 
        client.close(); 
        destroy = true; 
       } 
      } catch (IOException e) 
      { 
       try 
       { 
        client.close(); 
       } catch (IOException e1) 
       { 
        e1.printStackTrace(); 
        destroy = true; 
       } 
       System.out.println("Client lost connection."); 
       destroy = true; 
      } 
     } 
     System.out.println("TCPManager for client destroyed."); 
    } 
} 

命令:


package game.server; 

public class Commands 
{ 
    public static String proccessCommand(String command) 
    { 
     if(command.equalsIgnoreCase("cp")) 
     { 
      System.out.println("Creating player..."); 
       System.out.println(" Retrieved client"); 
      return "Player Created"; 
     } 
     else 
     { 
      return "Unkown command: " + command; 
     } 
    } 
} 
+1

僅供參考,除非您改變線程工作方式,否則不應該擴展'Thread'。在像你這樣的情況下,你只需要一個'run'方法就可以讓線程運行,實現'Runnable'並且說'new Thread(new TCPClientManager(clientSocket,clientID))。start();'獲得相同的功能暗示線程的工作方式不同。 – cHao

回答

1

如果您收到未知命令,應記錄它並關閉連接。

但是你有一個更嚴重的問題。當它讀取空值時,您不停止客戶端處理程序。所以一旦客戶斷開連接,閱讀將永遠無限地旋轉。如果readLine()返回null,則必須關閉套接字並退出循環。如果您得到任何IOException,則還必須關閉套接字。

+0

這是爲了成爲一款遊戲服務器,但我不希望它們在輸入無效命令時斷開連接。我如何經常檢查是否有收到的命令,如果我只是停止它,如果它等於空? – BleedObsidian

+1

@BleedObsidian:如果'readLine'返回null,這意味着客戶端已經關閉了連接的結束。你不會在這個連接上得到更多的命令。但是因爲你沒有退出循環,所以你只會一遍又一遍地閱讀空。 – cHao

+0

好的,我已經更新了我的代碼。但是現在如果有一個客戶端已經連接,它將不會接收另一個客戶端? – BleedObsidian