2017-08-15 17 views
1

私はMessageReceiverは、メッセージがTCP上で受信されるまで待機し、それらを処理し、メインループは、その情報を取得し、それに基づいて行動します2人の労働者エリクシルのワーカープロセス間でデータを共有するにはどうすればよいですか?

worker(Mmoserver.MessageReceiver, []), 
worker(Mmoserver.Main, []) 

を持っています。 worker1で取得した情報をworker2とどのように共有するのですか?

Mmoserver.ex
これは、これは単なるTCPリスナーを起動します労働者

defmodule Mmoserver do 
    use Application 

    def start(_type, _args) do 
    import Supervisor.Spec, warn: false 

    IO.puts "Listening for packets..." 

    children = [ 
     # We will add our children here later 

     worker(Mmoserver.MessageReceiver, []), 
     worker(Mmoserver.Main, []) 
    ] 

    # Start the main supervisor, and restart failed children individually 
    opts = [strategy: :one_for_one, name: AcmeUdpLogger.Supervisor] 
    Supervisor.start_link(children, opts) 
    end 

end 

MessageReceiver.ex
を開始し、メインファイルです。メインループであるMain.ex
、メッセージを取得し、それは(それのidによって)であるかを把握し、データを解析し、メイン

defmodule Mmoserver.MessageReceiver do 
    use GenServer 
    require Logger 

    def start_link(opts \\ []) do 
    GenServer.start_link(__MODULE__, :ok, opts) 
    end 

    def init (:ok) do 
    {:ok, _socket} = :gen_udp.open(21337) 
    end 

    # Handle UDP data 
    def handle_info({:udp, _socket, _ip, _port, data}, state) do 
    parse_packet(data) 
    # Logger.info "Received a secret message! " <> inspect(message) 
    {:noreply, state} 
    end 

    # Ignore everything else 
    def handle_info({_, _socket}, state) do 
    {:noreply, state} 
    end 

    def parse_packet(data) do 
    # Convert data to string, then split all data 
    # WARNING - SPLIT MAY BE EXPENSIVE 
    dataString = Kernel.inspect(data) 
    vars = String.split(dataString, ",") 

    # Get variables 
    packetID = Enum.at(vars, 0) 
    x = Enum.at(vars, 1) 

    # Do stuff with them 
    IO.puts "Packet ID:" 
    IO.puts packetID 
    IO.puts x 

    # send data to main 
    Mmoserver.Main.handle_data(vars) 
    end 
end 

に特定の機能に送信することができるはずです。これは、tcpリスナーによって受信された最新のすべてのデータを処理し、それを処理します。最終的にゲームの状態も更新されます。

defmodule Mmoserver.Main do 
    use GenServer 

    @tickDelay 33 

    def start_link(opts \\ []) do 
    GenServer.start_link(__MODULE__, [], name: Main) 
    end 

    def init (state) do 

    IO.puts "Main Server Loop started..." 

    # start the main loop, parameter is the initial tick value 
    mainLoop(0) 

    # return, why 1?? 
    {:ok, 1} 
    end 

    def handle_data(data) do 
    GenServer.cast(:main, {:handle_data, data}) 
    end 

    def handle_info({:handle_data, data}, state) do 
    # my_function(data) 
    IO.puts "Got here2" 
    IO.puts inspect(data) 
    {:noreply, state} 
    end 

    # calls respective game functions 
    def mainLoop(-1) do 
    IO.inspect "Server Loop has ended!" # base case, end of loop 
    end 

    def mainLoop(times) do 
    # do shit 
    # IO.inspect(times) # operation, or body of for loop 

    # sleep 
    :timer.sleep(@tickDelay); 

    # continue the loop RECURSIVELY 
    mainLoop(times + 1) 
    end 

end 

答えて

1

Mmoserver.MessageReceiverMmoserver.Mainにメッセージを送信しようとしているので、メインは、それが関連付けられている名前持っている必要があり、最初の場所で起動する必要があり、プラス:

worker(Mmoserver.Main, []), 
worker(Mmoserver.MessageReceiver, []) 

になる可能性が最も簡単な方法は、あなたのMmoserver.Mainで、それはGenServerであると仮定すると:

defmodule Mmoserver.Main do 
    use GenServer 

    def start_link do 
    GenServer.start_link(__MODULE__, [], name: :main) 
    end 

    # ... 
end 

ヨuはのような便利な機能に加え、一実装を追加することができます。これは、Mmoserver.MessageReceiverMmoserver.Mainが応答を期待していないと仮定し

defmodule Mmoserver.MessageReceiver do 
    def when_data_received(data) do 
    Mmoserver.Main.handle_data(data) 
    end 
end 

:だから

defmodule Mmoserver.Main do 
    # ... 

    def handle_data(data) do 
    GenServer.cast(:main, {:handle_data, data}) 
    end 

    def handle_info({:handle_data, data}, state) do 
    my_function(data) 
    {:noreply, state} 
    end 
end 

、あなたのMessageReceiverは、のようなメッセージを送ることができます。私はデータを扱う方法を指定していないので、このようにすることにしました。これは、これを行う方法の例です。

+2

可能性として 'GenStage'を調べることに言及する価値があるかもしれません。 –

+0

これはうまくいくようですが、最初に呼び出されない限りudpリスナーは機能しません。これはおそらく、Mainが壊れないループを開始するという事実と関係があります。私はそれらを持っていた順番にコールを入れ、udpリスナは動作し、メッセージがhandle_dataを通ってきたときにはcallendがhandle_infoではない。なぜ、私はちょうど今私のポストにコードを入れて – Diericx

+0

それは私が非同期であるために両方のプロセスが必要なので、メインは、TCPリスナーをブロックしていることを私も心配。 – Diericx

関連する問題