寻找以下问题的建议。
我正在使用一个应用程序(客户端),它使用单个TCP套接字来读取和写入服务器的消息。
消息是几种预定义类型之一,将在到达时进行解析。
服务器可以随时广播消息。
客户端将向服务器发送消息,并期待响应。但是(这里是我的问题所在),我无法从套接字读取接收此消息,因为我不知道何时可以传递它。大多数情况下,客户端响应消息将在客户端请求后立即传递。但是,偶尔会发送另一条广播消息。
套接字的读取通道由单个生产者线程排入阻塞队列。在单独的使用者线程中,任何消息都会出列并发送以供进一步处理。为了获得预期的客户端响应,我应该使用事件源/监听器习惯用法在他们(和如果)响应到达时通知我的客户端吗?
感谢您的任何建议。
编辑:我认为我的问题不清楚,因为到目前为止的建议并不涉及手头的问题。最后,我确实使用事件源/监听器习语来处理这个问题。再次感谢错误,但我认为这是关闭的。主持人甚至可能想要删除这个问题。答案 0 :(得分:0)
这是使用Java的序列化机制的绝佳机会。你可以做这样的事情(假设你正在捕捉所有相关的例外,为简洁起见省略了这些例外)
class ClientListeningThread {
ObjectInputStream in;
ObjectOutputStream out;
ClientListeningThread(Socket s) {
in = new ObjectInputStream(s.getInputStream());
out = new ObjectOutputStream(s.getOututStream());
}
public void run() {
while(true) {
ClientMessage message = (ClientMessage)in.readObject();
engine.addMessage(this,message); // add to the message queue, signifiying which listening thread to give the response to
}
}
public void send(ServerMessage message) {
out.writeObject(message);
}
}
您的消息甚至可以在其中进行回调
class LoginMessage {
public final String username;
public final String password;
public LoginMessage(String username, String password) {
this.username = username;
this.password = password;
}
public void callback(ClientListeningThread thread, ServerProcessor engine) {
ServerMessage response = engine.attemptLogin(username,password);
thread.send(response);
}
}
在您的引擎中
while(!requests.isEmpty()) {
ClientRequest request = requests.poll();
ClientListeningThread = request.thread;
ClientMessage message = request.message;
request.callback(thread,this);
}
答案 1 :(得分:0)
您可以使用侦听器和缓存的线程池来实现它。因此,您可以创建一个Runnable类来处理消息。然后创建一个侦听器类,它只是实例化一个套接字(或服务器套接字)并创建一个线程池。在你的listener类中创建一个无限的while循环,它监听传入的请求并将socket.accept传递给runnable对象的构造函数,以便它可以处理来自套接字的任何输入。
代码看起来像这样:
public class MessageHandler implements Runnable {
String msg = "";
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
public void MessageHandler(ServerSocket socket){
this.socket = socket;
}
@Override
public void run(){
//Message read from socket
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Message: " + in.readLine());
//Reply send back through same socket
out = new PrintWriter(socket.getOutputStream(), true);
out.println("MESSAGE RECEIVED. THANKS.");
}
}
你听课会看起来像这样:
public class SocketListener {
ServerSocket socket = null;
ExecutorService threadExecutor = null;
Runnable runnable = null;
public static void main (String[] args){
socket = new ServerSocket(8181);
/* Socket will always be listening, when a request arrives a thread will handle
* the incoming stream.
*/
while(true) {
threadExecutor = Executors.newCachedThreadPool();
runnable = new MessageHandler(socket.accept);
threadExecutor.execute(runnable);
}
}
}
我不确定这段代码是否会编译,但您的服务器实现看起来与此类似,并且可扩展且强大。
您的客户端几乎完全相同,但您将使用套接字而不是 ServerSocket ,并且可能以不同方式处理您的消息。