【发布时间】:2014-01-23 04:15:34
【问题描述】:
尝试说明情况:
我创建了一个 SocketManager 类。这扩展了 JavaFX 服务,旨在创建新线程(我已扩展并称为 SocketListener 的 JavaFX 任务)来处理特定的套接字连接。
在 SocketListener 中,我有一个循环侦听套接字上的输入(并回复客户端)。
问题:SocketListener 中的循环被阻塞(显然)。这意味着我永远不会到达 Socket Listener(扩展 JavaFX 任务)的调用方法中的“返回”。 我很好奇要实现什么模式,这样我就可以从 SocketListener 返回一个值,而不必中断与客户端保持连接的循环。想到的一个想法是创建一个自定义事件以在每条消息通过套接字时触发,但我想确保我实现的任何东西不仅“工作”而且是最佳的。
这是我引用的两个类的代码:
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* The primary class for listening for and issuing communication over sockets in VDTS
* applications.
* WARNING: This class is blocking, and should be run in a separate thread.
*/
public class SocketManager extends Service<SocketMessage> {
/**
* The port that SocketManager instance will listen on.
*/
int listenPort;
/**
* The ServerSocket instance used by SocketManager for receiving socket connections.
*/
ServerSocket server;
/**
* Constructs a SocketManager and begins listening on the given port.
* @param listenPort The port that the SocketManager instance will listen on.
*/
public SocketManager(int listenPort){
this.listenPort = listenPort;
try {
this.server = new ServerSocket(listenPort);
} catch (IOException ex) {
System.out.println(ex.getMessage());
//TODO
}
}
/**
* Returns the port currently being listened to by SocketManager instance.
* @return the port being listened to.
*/
public int getListenPort() {
return listenPort;
}
/**
* Sets a new port for the SocketManager instance to listen to. This will destroy
* the current ServerSocket, ending any communication via the old instance. Use
* with caution.
* @param listenPort The new port this SocketManager instance will listen on.
*/
public void setListenPort(int listenPort) {
this.listenPort = listenPort;
}
@Override
protected Task createTask() {
String returnedMessage;
Socket client;
SocketListener messenger;
while(true){
try {
client = null;
client = server.accept();
messenger = new SocketListener(client);
new Thread(messenger).start();
} catch (IOException ex) {
System.out.println(ex.getMessage());
//TODO
}
}
}
}
还有一个
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* An extension on javafx.concurrency.Task.
* SocketListener is responsible for retrieving a message (string) from a client over
* the socket and returning this string (Usually to a SocketManager).
*/
public class SocketListener extends javafx.concurrent.Task<String> {
/**
* Client socket which is referenced for persistent communication.
*/
private final Socket client;
/**
* PrintWriter used to write to client.
*/
private PrintWriter clientOut;
//TODO This is a temporary property for testing, remove it;
private int messageCount = 0;
/**
* Constructs a SocketListener given a client (Socket)
* @param client
*/
public SocketListener(Socket client){
this.client = client;
try {
this.clientOut = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Listens for and returns the value of the message received over socket.
* @return The message received from the client.
* @throws Exception
*/
@Override
protected String call() throws Exception {
String nextLine = null;
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
//TODO remove in production should not require highfive
clientOut.println("Just saying hi.");
while ((nextLine = in.readLine()) != null) {
this.messageCount++;
clientOut.println("You've messaged me " + this.messageCount + " times.");
}
return "Socket closed.";
}
}
【问题讨论】: