Java 如何在不阻止其他请求的情况下侦听套接字输入
我的标题可能不是最具描述性的,但我将尝试展示尽可能多的代码,希望它能帮助大家更好地理解我的问题。下面是我的项目客户端如何查询服务器以获取信息。这是一个典型请求的示例:Java 如何在不阻止其他请求的情况下侦听套接字输入,java,multithreading,sockets,Java,Multithreading,Sockets,我的标题可能不是最具描述性的,但我将尝试展示尽可能多的代码,希望它能帮助大家更好地理解我的问题。下面是我的项目客户端如何查询服务器以获取信息。这是一个典型请求的示例: private String GENERATEGROUPKEY() { /* `out` is a PrintWriter using the sockets output stream */ out.println("GENERATEGROUPKEY"); try { /* `i
private String GENERATEGROUPKEY()
{
/* `out` is a PrintWriter using the sockets output stream */
out.println("GENERATEGROUPKEY");
try
{
/* `in` is a BufferedReader using the sockets input stream */
String response = in.readLine();
String[] temp = response.split(" ");
return temp[1];
}
catch (IOException ex)
{
return null; // throw connection error to client
}
}
我的问题是,在任何时候,服务器都可以通过同一个套接字向客户端发送一条未经请求的消息,其中包含信息(将其视为聊天客户端接收消息)。我不成功的想法是创建一个线程来侦听这样的消息,只要我们不在另一个查询的中间,但是这也是不成功的,因为即使我中断了这个线程,它仍然占用了应该转到客户端查询的消息。
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()
。我想中断线程的想法是行不通的。正确的方法是什么?这里的一般模式是,您需要一个线程处理套接字的输出(等待时阻塞),然后将消息发送到请求它们的正确对象
我喜欢并在多个项目中成功使用的一个实现是将随机生成的ID添加到“请求”中,作为通用头的一部分(也包括消息类型),并让服务器始终在响应中镜像该ID,它允许客户端将请求与响应关联起来,而不必关心它是什么类型的消息
具体来说,类似于带有两个公共函数的SocketMessenger
类:sendRequest(类型、正文、回调)
和registerUnsolicitedHandler(类型、回调)
sendRequest
使用type
和随机生成的ID构建消息头,将其添加到待处理回复列表中以及对回调函数的引用,然后将完成的消息发送到服务器
registerUnsolicitedHandler
按照其名称执行操作,并将回调函数添加到传入消息没有ID时要使用的消息类型映射中
在处理传入消息的单独线程中,它反序列化传入数据以从报头获取类型和ID,如果消息具有ID,它将搜索挂起的回复列表,并使用消息体调用相应的回调(可能是在主线程上安排的,我会忽略一些细节,如锁定),否则,它将在未经请求的处理程序列表中搜索指定类型并调用该回调。With,err?它在哪里说中断线程会取消它被阻塞的I/O操作?@EJP这不是一个多线程问题吗?我不确定在一个合法且独特的问题上的-1是否合适,但我离题了。Javadocs说,我引用,“如果这个线程在可中断通道上的I/O操作中被阻塞,那么通道将被关闭。”这对我不适用吗?如果不是的话,我可能的解决方案是什么,因为我不知道我需要做什么。@Headline实际引用如java类中所述。BufferedReader可能正在引发异常,但由于您没有对其执行任何操作,因此您不会知道。此外,如果您正在使用通道,并且您中断正在读取该通道的线程,它将关闭该通道。。。没有别的东西可以从那个频道读到。