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

时间:2017-02-05 14:34:09

标签: java sockets

这里我创建一个线程来检查每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);

我通过服务器发送响应,如此(其中client是已建立的套接字):

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);
}

然后我通过已连接到服务器的客户端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();
}

调试控制台只显示侦听响应... 输出,告诉我它没有通过线程内的inputStream.readLine()方法。无论如何我可以在BufferedReader上添加超时吗?我尝试了多种解决方案,例如在创建BufferedReader之前向套接字添加.setSoTimeout(),但所有这些都是在指定时间后关闭连接/套接字。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

您应该使用非阻塞(NIO)请求并读取块以查找中间的换行符。通常在Java中,您只需要查找正在使用的Stream类的NIO版本,并使用它来检查新内容的每N秒。在您进行最少修改的情况下,您可以使用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 "";
}

查看http://tutorials.jenkov.com/java-nio/nio-vs-io.html了解详情。

答案 1 :(得分:0)

  

无论如何我可以在BufferedReader上添加超时吗?

不,但您可以使用SocketSocket.setSoTimeout()上设置超时。

  

在创建BufferedReader之前,我尝试过多个解决方案,例如在套接字中添加.setSoTimeout(),但所有这些都是在指定时间后关闭连接/套接字。

不,它没有关闭套接字。它抛出SocketTimeoutException,你应该抓住并处理相关的内容。如果套接字正在关闭,您将关闭它。解决方案:不要。