【发布时间】:2015-03-24 19:37:08
【问题描述】:
我有一个在后台运行的 akka 任务来监听 UDP 包。但是,当我这样做时,我对代码进行了更改,系统会重新编译,但随后会停止/挂起,我需要完全停止并重新启动(如果每次更改后都需要这样做,这需要很长时间)。当我不启动客家任务时,它工作正常。这是控制台输出:
[info] play - database [default] connected at jdbc:h2:mem:play
[info] play - Starting application default Akka system.
[info] application - Starting UDP server
[info] play - Application started (Dev)
[debug] application - Ready to receive broadcast packets!
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[info] Compiling 1 Scala source and 1 Java source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
[success] Compiled in 6s
[info] Compiling 1 Scala source to /Users/Luuk/Documents/Java/temperature-control/target/scala-2.11/classes...
--- (RELOAD) ---
[info] play - Shutdown application default Akka system.
我正在使用 IDEA 14。
这是我的全局: 公共类 Global 扩展 GlobalSettings {
@Override
public void onStart(Application app) {
if (SensorRole.find.findRowCount() != SensorRole.RoleName.values().length) {
for (SensorRole.RoleName roleName : SensorRole.RoleName.values()) {
SensorRole newRole = new SensorRole();
newRole.name = roleName.toString();
newRole.save();
}
}
ActorRef instance = Akka.system().actorOf(Props.create(UDPBroadcastServer.class), "UDPServer");
instance.tell("Start", ActorRef.noSender());
super.onStart(app);
}
@Override
public void onStop(Application app){
Logger.debug("Stopping system...");
Akka.system().shutdown();
super.onStop(app);
}
}
和 UDPBroadcastServer:
public class UDPBroadcastServer extends UntypedActor {
DatagramSocket socket;
boolean stop;
@Override
public void postStop() throws Exception {
super.postStop();
stop = true;
Logger.info("Master Killed");
}
@Override
public void onReceive(Object command) throws Exception {
Logger.info("Starting UDP server");
stop = false;
String action = (String) command;
if (action.equals("Start")) {
try {
//Keep a socket open to listen to all the UDP trafic that is destined for this port
socket = new DatagramSocket(8888, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (!stop) {
Logger.debug("Ready to receive broadcast packets!");
//Receive a packet
byte[] recvBuf = new byte[15000];
packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet);
//Packet received
Logger.debug("Discovery packet received from: " + packet.getAddress().getHostAddress());
Logger.debug("Packet received; data: " + new String(packet.getData()));
//See if the packet holds the right command (message)
String message = new String(packet.getData()).trim();
if (message.equals("DISCOVER_TEMPSERVER_REQUEST")) {
byte[] sendData = "DISCOVER_TEMPSERVER_RESPONSE".getBytes();
//Send a response
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
socket.send(sendPacket);
Logger.debug("Sent packet to: " + sendPacket.getAddress().getHostAddress());
}
}
} catch (IOException ex) {
Logger.error("Problem with UDP server:" + ex.getLocalizedMessage());
}
} else if (action.equals("Stop")) {
Logger.debug("Trying to stop process!");
stop = true;
if(packet != null) packet = null;
if(socket.isConnected()) socket.close();
}
}
[编辑]: 根据推荐,我正在尝试手动停止任务。但是,我无法重新获得 ActorRef 的句柄。我正在尝试这样做:
ActorRef test = Akka.system().actorFor("//application/user/UDPServer");
test.tell("Stop", ActorRef.noSender());
Logger.debug("Path: " + test.path());
Akka.system().stop(test);
但是 Actor 的 'onReceive' 永远不会收到 'Stop'。
【问题讨论】:
-
我猜你的演员在
socket.receive(packet)上被屏蔽了。从文档中,您可以理解原因:This method blocks until a datagram is received.,因此您的停止标志没有意义。 -
好的,有道理。我现在正在尝试关闭套接字,但似乎无法处理已经激活的 tsk。我使用 test.tell("Stop", ActorRef.noSender());根据上面的代码,但没有收到任何东西。也许我应该为套接字创建一个单独的线程。
-
我把套接字放在一个单独的线程中,现在 olnrecieve 可以接收调用,并关闭套接字,一切正常(我在 Play Global 的 onStop 上添加了停止。)如果你想把答案放进去,然后我会接受你指出的问题。
-
嗨,谢谢。我将这些 cmets 复制到答案中。
标签: java playframework-2.0 akka