确保客户端请求得到正确的响应

时间:2011-04-25 20:46:14

标签: java sockets

寻找以下问题的建议。

我正在使用一个应用程序(客户端),它使用单个TCP套接字来读取和写入服务器的消息。

消息是几种预定义类型之一,将在到达时进行解析。

服务器可以随时广播消息。

客户端将向服务器发送消息,并期待响应。但是(这里是我的问题所在),我无法从套接字读取接收此消息,因为我不知道何时可以传递它。大多数情况下,客户端响应消息将在客户端请求后立即传递。但是,偶尔会发送另一条广播消息。

套接字的读取通道由单个生产者线程排入阻塞队列。在单独的使用者线程中,任何消息都会出列并发送以供进一步处理。为了获得预期的客户端响应,我应该使用事件源/监听器习惯用法在他们(和如果)响应到达时通知我的客户端吗?

感谢您的任何建议。

编辑:我认为我的问题不清楚,因为到目前为止的建议并不涉及手头的问题。最后,我确实使用事件源/监听器习语来处理这个问题。再次感谢错误,但我认为这是关闭的。主持人甚至可能想要删除这个问题。

2 个答案:

答案 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 ,并且可能以不同方式处理您的消息。