2015-10-26 32 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可以很好地扩展,但是单个状态机在需要的输入上阻塞(或者需要传递确认)并不需要在线程池中扩展或者等待复杂的事件回调。当然,其他人可能会有不同的看法,但某些工作流程可以通过较少扩展性的解决方案进行更快速的基准测试(我认为这可能是一项工作,可扩展性不会给您带来太多的收益,除非您真的为几十个或更多数百台状态机在同一进程中)。