如何在不阻止其他请求的情况下侦听套接字输入

时间:2017-12-21 10:28:02

标签: java multithreading sockets

我的标题可能不是最具描述性的,但我会尽量展示尽可能多的代码,希望它能帮助每个人更好地理解我的问题。以下是我的项目客户端查询服务器以获取信息的方式。这是典型请求的示例:

private String GENERATEGROUPKEY()
{
    out.println("GENERATEGROUPKEY");
    listenThread.interrupt(); // block listenThread from recieving response

    try
    {
        String response = in.readLine();
        String[] temp = response.split(" ");

        listenThread = new PulseThread(in); // we're done, so allow 
        listenThread.start();
        return temp[1];
    }
    catch (IOException ex)
    {
        listenThread = new PulseThread(in); // we're done, so allow
        listenThread.start(); 
        return null; // throw connection error to client
    }
}

我的问题是,服务器可以随时通过同一个带有信息的套接字向客户端发送未经请求的消息(想想它就像聊天客户端接收消息一样)。我的不成功的想法是创建一个侦听这样一条消息的线程,只要我们不在另一个查询的中间,但这也是不成功的,因为即使我正在打断该线程,它仍然会占用应该的消息已经去了客户端查询。

listenThread

这正是public class PulseThread extends Thread { private BufferedReader in; public PulseThread(BufferedReader in) { this.in = in; } @Override public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { break; } try { String line = in.readLine(); System.out.println(line); String[] params = line.split(" "); if (params[0].equals("PULSED")) { NotificationManager.sendNotification("You have been pulsed!", "Pulsed by: " + params[1]); } } catch (Exception ex) { } } } }

的内容
BufferedReader

我之前的印象是,在使用readLine()的{​​{1}}阻止呼叫中间中断线程只会取消阻止呼叫,除非我做错了其他事情。

非常感谢任何帮助,谢谢。

编辑:所以在我的假设上只比这句话高几行,似乎中断线程不会取消readLine()。我猜中断线程的想法是不行的。什么是正确的方法?

1 个答案:

答案 0 :(得分:2)

这里的一般模式是你想要一个线程处理来自套接字的输出(在等待时阻塞),然后将消息分派给请求它们的正确的东西。

我喜欢并在多个项目中成功使用的一个实现是将随机生成的ID添加到“请求”作为通用标头的一部分(包括消息类型),并让服务器始终将ID重新映射到响应,允许客户端将请求与响应相关联,而不关心它是什么类型的消息。

具体而言,类似于具有2个公共函数的SocketMessenger类:sendRequest(type, body, callback)registerUnsolicitedHandler(type, callback)

sendRequest使用type和随机生成的ID构建邮件头,将其添加到待处理回复列表以及对回调函数的引用,然后将完成的邮件发送到服务器。

registerUnsolicitedHandler执行其名称建议,并将回调函数添加到消息类型的映射中,以便在传入消息没有ID时使用。

在处理传入消息的单独线程中,它对传入数据进行反序列化以从头部获取类型和ID,如果消息具有ID,则它会搜索待处理的回复列表并使用消息正文调用相应的回调(可能已安排在主线程,我正在掩盖锁定等一些细节,否则它会在未经请求的处理程序列表中搜索指定的类型并调用该回调。