我有2名工人
worker(Mmoserver.MessageReceiver, []),
worker(Mmoserver.Main, [])
MessageReceiver将等待直到在TCP上接收到消息并处理它们,主循环将获取该信息并对其进行操作。如何与worker2共享worker1获取的信息?
Mmoserver.ex
这是启动工作人员的主文件
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
这只会启动一个tcp监听器。它应该能够获取消息,找出它是什么(通过它的id)然后解析数据并将其发送到Main中的特定函数
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
Main.ex
这是主循环。它将处理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
答案 0 :(得分:1)
由于Mmoserver.MessageReceiver
将向Mmoserver.Main
发送消息, 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
您可以添加便利功能,以及类似的实现:
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
可以发送如下消息:
defmodule Mmoserver.MessageReceiver do
def when_data_received(data) do
Mmoserver.Main.handle_data(data)
end
end
这假设Mmoserver.MessageReceiver
并不期望Mmoserver.Main
做出回应。我已经决定这样做,因为你没有指定你想要处理数据的方式,这似乎是如何做到这一点的简单例子。