简体   繁体   English

如何使用套接字流在BufferedReader上设置超时

[英]How to set a timeout on a BufferedReader with a socket stream

Here I am creating a thread to check for a server response every 2 seconds, the issue is that the client.monitorResponse() is a readLine() method and will not continue until a response is received. 这里我创建一个线程来检查每2秒的服务器响应,问题是client.monitorResponse()是一个readLine()方法,并且在收到响应之前不会继续。

client = new ClientObject("localhost");
timer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        try {
            String response = null;
            if(!(response = client.monitorResponse()).isEmpty()) {
                System.out.println("Response: " + response);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}, 2000, 2000);

I am sending the response via the Server like so (where client is a established Socket): 我通过服务器发送响应,如此( client是已建立的Socket):

public SocketObject(Socket client, int numberOfClients) throws Exception {
    socket = client; // the .accept() socket is passed through
    // this is because I assign them ID's for later use (I hold an ArrayList of sockets)
    this.clientId = numberOfClients;

    // both these are static to the class

    outputStream = new PrintWriter(client.getOutputStream());
    inputStream = new BufferedReader(new InputStreamReader(client.getInputStream()));
}

public void sendResponse(String response) {
    outputStream.println(response);
}

I am then picking the response up via the client Socket that has connected to the server: 然后,我通过已连接到服务器的客户端Socket选择响应:

public ClientObject(String hostname) throws IOException {

    // socket is static to this class

    socket = new Socket(hostname, 4444);
    System.out.println("Connected to " + hostname + " on port 4444...");

    // both static to this class

    outputStream = new PrintWriter(socket.getOutputStream(), true);
    inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    System.out.println("Successfully started a stream on " + hostname);
    this.hostname = hostname;
}

public String monitorResponse() throws Exception {
    System.out.println("Listening for a response...");
    return inputStream.readLine();
}

The debug console only displays the Listening for a response... output once which is telling me that it doesn't get past the inputStream.readLine() method in-side the Thread. 调试控制台只显示一个侦听响应...输出,它告诉我它没有通过Thread内部的inputStream.readLine()方法。 Is there anyway I can add a timeout on the BufferedReader? 无论如何我可以在BufferedReader上添加超时吗? I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time. 我已经尝试了多种解决方案,比如在创建BufferedReader之前向套接字添加.setSoTimeout() ,但所有这些都是在指定时间后关闭连接/套接字。

Any help would be appreciated. 任何帮助,将不胜感激。

You should use a non-blocking (NIO) request and read chunks looking for newlines in-between. 您应该使用非阻塞(NIO)请求并读取块以查找中间的换行符。 Typically in Java you just have to look for the NIO version of the Stream class you are using and use it to check every N seconds for new content. 通常在Java中,您只需要查找正在使用的Stream类的NIO版本,并使用它来检查新内容的每N秒。 In your case with minimal modifications you can use the less fancy and efficient method of blocking calls with BufferedReader.ready() to prevent blocking: 在您进行最少修改的情况下,您可以使用BufferedReader.ready()阻止调用的不那么花哨和有效的方法来防止阻塞:

String partialLine="";
public static String monitorResponse() throws Exception {
    System.out.println("Listening for a response...");
    int nextByte;
    String nextChar;
    while (inputStream.ready()) {
        nextByte = inputStream.read();
        nextChar = Character.toString ((char) nextByte);
        partialLine += nextChar;
        if ("\n".equals(nextChar)) {
            String line = partialLine;
            partialLine = "";
            return line.replace("\r\n", "");
        }
    }
    return "";
}

Check out http://tutorials.jenkov.com/java-nio/nio-vs-io.html for more info. 查看http://tutorials.jenkov.com/java-nio/nio-vs-io.html了解更多信息。

Is there anyway I can add a timeout on the BufferedReader? 无论如何我可以在BufferedReader上添加超时吗?

No, but you can set a timeout on the Socket , with Socket.setSoTimeout() . 不,但您可以使用Socket.setSoTimeout()Socket上设置超时。

I have tried multiple solutions like adding a .setSoTimeout() to the socket before creating the BufferedReader but all that did was close the connection/socket after the specified time. 我已经尝试了多种解决方案,比如在创建BufferedReader之前向套接字添加.setSoTimeout(),但所有这些都是在指定时间后关闭连接/套接字。

No it doesn't close the socket. 不,它没有关闭插座。 It throws SocketTimeoutException , which you should catch and handle as pertinent. 它抛出SocketTimeoutException ,你应该捕获并处理相关的。 If the socket is being closed, you're closing it. 如果套接字正在关闭,您将关闭它。 Solution: don't. 解决方案:不要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM