2015-12-09 88 views
2

我已經實現了一個基本的TCP客戶端和服務器。客戶端從輸入流發送命令。服務器處理收到的消息並回復客戶端。從不同的線程收集數據

我想測試通過以下方式我的客戶端 - 服務器解決方案:

  1. 創建多個客戶端線程;
  2. 每個客戶端線程將從文件讀取命令並將它們發送到服務器;
  3. 服務器回覆後,每個客戶端必須收集回覆到列表;

我想尋求任何代碼審查和任何建議(我將不勝感激任何實例)如何收集服務器迴應從每個客戶端線程的列表。目前,我不能夠收集來自所有客戶端線程的所有答覆中ClientList<String> messages

類派生ClientTask

public class Client { 
private static Logger logger = Logger.getLogger(Client.class); 
private File configs; 
private InputStream inputStream; 
private int port; 
private String ip; 


public Client(File file, InputStream inputStream) { 
    this.configs = file; 
    this.inputStream = inputStream; 
    Map<String, Object> configs = ConfigLoader.loadXMLConfigsFromFile(file); 
    this.port = (Integer) configs.get("port"); 
    this.ip = (String) configs.get("ip"); 
} 

// 
public void start(int numberOfThreads, List<String> messages) throws InterruptedException { 
    for (int i = 0; i < numberOfThreads; i++) { 
     List<String> collectedServerReply = Collections.synchronizedList(new ArrayList<>()); 
     try { 
      Thread clientThread = new Thread(
        new ClientTask(port, ip) 
          .setInputStream(new FileInputStream("commands.txt")) 
          .setReplyListener(message -> { 
           //messages.add(message.receive().getMessage()); 
           collectedServerReply.add(message.receive().getMessage()); 
           //System.out.println("current stack size: " + messages.size()); 
          })); 
      clientThread.start(); 
      System.out.println("finished client thread"); 
     } catch (IOException e) { 
      logger.error("Exception occurred while reading from System.in. Exception: ", e); 
     } 
     messages.addAll(collectedServerReply); 
    } 
} 
} 

Client類固定數量的具有接受一個實現ReplyListerner接口的任何實例的二傳手。後者服務器作爲一個抽象收集的答覆數據:

public interface ReplyListener { 

    void onReply(Message message) throws IOException; 
} 

我不能收集所有服務器的應答的方法中public void start(int numberOfThreads, List<String> messages)。然而,當我只是做到以下幾點:

Thread clientThread = new Thread(
         new ClientTask(port, ip) 
           .setInputStream(new FileInputStream("commands.txt")) 
           .setReplyListener(message -> { 
            System.out.println(message.receive().toString());})); 

我可以看到我的System.in

哪裏我犯了一個錯誤適當的服務器的答覆,我如何能實現我的收集服務器回覆的目標是什麼?

編輯:

我如何使用我的實現:

public static void main(String[] args) throws IOException, InterruptedException { 
    List<String> collectedMessages = Collections.synchronizedList(new ArrayList<>()); 

    Thread serverThread = new Thread(new ServerLauncher(new File("config.xml"))); 
    serverThread.setName("server_thread"); 
    serverThread.start(); 
    new Client(new File("config.xml"), new FileInputStream("commands.txt")).start(1, collectedMessages); 
    System.out.println("Collected output ..."); 
    for (int i = 0; i < collectedMessages.size(); i++) { 
     System.out.println(collectedMessages.get(i)); 
    } 
} 

回答

0

如果使用非同步實施的List你可能有競爭條件。

顯式同步:

synchronized(messages) 
    messages.addAll(collectedServerReply); 
} 

或確保調用使用同步的列表中選擇啓動功能,例如Vector

編輯 - 以下你的。確保在顯示您的列表之前等待所有線程完成。

clientThread.join(); 

當然,在第二個循環中執行該操作或者您失去了多線程的所有優勢。

+0

我在同步列表上調用我的客戶端實例。請參閱編輯。 –

+0

@ mr.M萬一你沒有看到 - 我編輯了我的答案。 – cadrian

+0

當我用你的建議測試我的應用時,我會盡快通知你=) –