2015-10-26 31 views
0

我一直在使用一個簡單的eclipse插件來創建可視狀態機,稱爲statecharts,它也使用Java代碼來工作。我的總體目標是讓兩臺狀態機通過套接字互相通信並交換數據並根據這些數據進行轉換,例如客戶端 - 服務器通信。 在開始時,我使用簡單的同步客戶端 - 服務器代碼,但顯然使用同步方法無法提供幫助;正確的方法是連續輪詢隊列中的數據。我現在試圖使用Java NIO這似乎很有前途,但不幸的是在第一次嘗試中沒有成功。似乎有一個忙碌的循環,不允許接收到的值觸發更改。代碼很簡單:我首先嚐試連接到服務器(它工作),發送一個數據(它工作),並嘗試從輸入緩衝區讀取每個週期作爲接收數據的一種方式,您可以看到圖片。迄今爲止的邏輯是合理的。我將收到的數據設置爲一個也位於轉換表達式中的變量。所以基本上每當它被設置爲真時,我應該轉換到下一個狀態。但它不起作用。Java中兩個狀態機之間的通信

有人可以幫我解決這個問題嗎?我看到有異步API,如NettyNaga,如果這是一種補救措施,可能會使事情變得更容易。

這裏是一個狀態機的可視化方案: enter image description here

這裏是客戶端的代碼:

package test; 

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

public class EchoClient2 { 
    String serverHostname = new String("127.0.0.1"); 
    BufferedReader stdIn; 
    Socket echoSocket = null; 
    PrintWriter out = null; 
    BufferedReader in = null; 

    public void open(){ 
     System.out.println("Attemping to connect to host " + serverHostname 
       + " on port 5555."); 
     try { 
      echoSocket = new Socket(serverHostname, 5555); 
      out = new PrintWriter(echoSocket.getOutputStream(), true); 
      in = new BufferedReader(new InputStreamReader(
        echoSocket.getInputStream())); 
     } catch (UnknownHostException e) { 
      System.err.println("Don't know about host: " + serverHostname); 
     } catch (IOException e) { 
      System.err.println("Couldn't get I/O for " + "the connection to: " 
        + serverHostname); 
     } 
    } 

    public void send(){ 
     String userInput = "1"; 
     out.println(userInput); 
    } 

    public String receive(){ 
     String result = ""; 
     try { 
      result = in.readLine(); 
      if(result==null) 
       return "0"; 
     } catch (IOException e) { 
     } 
     return result; 
    } 
} 

這裏是服務器的代碼:

package test; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class EchoServer extends Thread { 
    protected Socket clientSocket; 

    public static void main(String[] args) throws IOException { 
     ServerSocket serverSocket = null; 

     try { 
      serverSocket = new ServerSocket(5555); 
      System.out.println("Connection Socket Created"); 
      try { 
       while (true) { 
        System.out.println("Waiting for Connection"); 
        new EchoServer(serverSocket.accept()); 
       } 
      } catch (IOException e) { 
       System.err.println("Accept failed."); 
       System.exit(1); 
      } 
     } catch (IOException e) { 
      System.err.println("Could not listen on port: 5555."); 
      System.exit(1); 
     } finally { 
      try { 
       serverSocket.close(); 
      } catch (IOException e) { 
       System.err.println("Could not close port: 5555."); 
       System.exit(1); 
      } 
     } 
    } 

    private EchoServer(Socket clientSoc) { 
     clientSocket = clientSoc; 
     start(); 
    } 

    public void run() { 
     System.out.println("New Communication Thread Started"); 

     try { 
      PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), 
        true); 
      BufferedReader in = new BufferedReader(new InputStreamReader(
        clientSocket.getInputStream())); 

      String inputLine; 

      while ((inputLine = in.readLine()) != null) { 
       System.out.println("Server: " + inputLine); 
       out.println(inputLine); 

       if (inputLine.equals("Bye.")) 
        break; 
      } 

      out.close(); 
      in.close(); 
      clientSocket.close(); 
     } catch (IOException e) { 
      System.err.println("Problem with Communication Server"); 
      System.exit(1); 
     } 
    } 
} 

而且here是Eclipse項目文件夾,您可以簡單地導入,如果該mi要容易些。

回答

1

你打算做什麼後面的數學叫做PI微積分。這不是唯一的方法,但它是一個開始的好地方。

基本上,你將建模的關係是兩臺機器可以進入相關狀態,直到發生共享條件(通常是一條消息被傳遞)纔會進展。

這意味着您將不得不在兩個獨立的線程上同時使用狀態機。試圖使用公共事件隊列來排序機器,如果排序不穩定(如果排序不能補充某個問題,則可能更成問題),這會變得非常成問題。

通常共享消息被簡化。例如,許多系統使用「郵箱」類型的傳遞機制,其中一個狀態機將消息傳遞給另一個的入站郵箱。然後交付狀態機阻塞,直到消息清除郵箱。如果您以正確的方式對此進行了形式化,則可以有效地創建像解決方案這樣的Actor。如果您認爲這是您可能想繼續進行的方式,則儘早在郵箱中進行烘焙可讓您稍後用持久性消息傳遞系統替換該類。我們最喜歡的方法是讓第三個進程啓動這兩個進程,其中啓動進程還創建任何所需的通信通道。該啓動過程可以設置其兩個孩子的可配置元素。以這種方式做事可能需要一點關於如何在沒有ttys的情況下創建「系統服務」aka程序的知識,但這是很好的知識。另外我更喜歡JMS API和許多實現之一。

如果你真的想「自己動手」,那麼我會開始使用一些比完整的NIO解決方案少一些的東西。記住,當你有特定的通信模式時,NIO可以很好地擴展,但是單個狀態機在需要的輸入上阻塞(或者需要傳遞確認)並不需要在線程池中擴展或者等待複雜的事件回調。當然,其他人可能會有不同的看法,但某些工作流程可以通過較少擴展性的解決方案進行更快速的基準測試(我認爲這可能是一項工作,可擴展性不會給您帶來太多的收益,除非您真的爲幾十個或更多數百臺狀態機在同一進程中)。