2015-10-26 6 views
0

Я использую простой плагин eclipse для создания визуальных состояний машин под названием statecharts, который также использует Java-код для работы. Моя общая цель состоит в том, чтобы заставить две государственные машины взаимодействовать друг с другом через сокеты и обмениваться данными и делать на них переходы, такие как связь клиент-сервер. В начале я использовал простой синхронный клиент-серверный код, но, по-видимому, использование синхронного подхода не может помочь; правильным способом является непрерывный опрос данных из очереди. Теперь я пытаюсь использовать Java NIO, который кажется многообещающим, но, к сожалению, не имел успеха с первой попытки. Кажется, что есть занятый цикл где-то, что не позволяет полученному значению инициировать изменение.Связь между двумя государственными машинами в Java

Код довольно прост: сначала я пытаюсь подключиться к серверу (он работает), отправлять данные (он работает) и пытаться читать из входного буфера каждый цикл как способ получения данных, как вы можете видеть в изображение. Логика до сих пор имеет смысл. Я устанавливаю полученные данные в переменную, которая также находится в выражении перехода. Поэтому в принципе, когда это задано, я должен перейти в следующее состояние. Но это не сработает.

Может ли кто-нибудь помочь мне решить эту проблему? Я видел, что есть асинхронные API, такие как Netty и Naga, которые могут облегчить ситуацию, если это средство.

Вот визуальная схема государственной машины: 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 ght быть проще.

ответ

1

Математика за то, что вы намереваетесь сделать, называется PI Calculus. Это не единственный подход, но это отличное место для начала.

В основном то, что вы будете моделировать, - это отношения, в которых две машины могут вводить связанные состояния и не прогрессировать до тех пор, пока не произойдет общее условие (которое обычно является передаваемым сообщением).

Это означает, что вам придется иметь обе ваши государственные машины на отдельных потоках. Попытка использовать общую очередь событий заказывает машины, которые могут стать очень проблематичными, если упорядочение нестабильно (и может быть еще более проблематичным, если упорядочение не является дополнением к определенной проблеме).

Часто распространенное сообщение упрощается. Например, во многих системах используется механизм доставки типа «почтовый ящик», где один конечный автомат отправляет сообщение во входящий почтовый ящик другого. Затем конечный автомат доставки блокирует до тех пор, пока сообщение не очистит почтовый ящик. Если вы правильно оформляете это, вы эффективно создаете решение, подобное Актеру. Если вы решите, что это способ, которым вы, возможно, захотите продолжить, выпечка в почтовом ящике на раннем этапе позволит вам позже заменить класс на постоянную систему доставки сообщений.

Что касается фактической работы с двумя независимыми процессами, мой любимый подход заключается в том, чтобы запустить третий процесс, когда процесс запуска также создает любые необходимые каналы связи. Этот процесс запуска может затем установить настраиваемые элементы из двух детей. Выполнение этого способа может потребовать немного знаний о том, как создавать «системные службы», например, программы без ttys, но это хорошие знания.Также я предпочитаю JMS API и одну из многих реализаций.

Если вы действительно хотите «сворачивать свои собственные», то я бы начал с чего-то чуть-чуть меньше, чем полномасштабное решение NIO. Помните, что NIO хорошо масштабируется, когда у вас есть определенные шаблоны связи, но единичный государственный механизм, блокирующий необходимый вход (или необходимое подтверждение доставки), не нужно масштабировать через пулы потоков или ждать сложных обратных вызовов событий. Конечно, другие могут расходиться во мнениях, но некоторые потоки работы быстрее ориентируются на менее масштабируемое решение (и я думаю, что это может быть задача, при которой масштабируемость не собирается покупать вас много, если вы действительно не проксимируете связь для десятков или сотни государственных машин в том же процессе).