关于从TCP连接读取的数据

时间:2013-08-16 09:41:31

标签: java tcp

我正在与硬件设备建立客户端套接字连接。我正在向此连接发送命令以通过硬件进行处理。现在作为确认或回复,硬件发送响应。  应用程序会在10秒内定期向连接发送命令。

现在存在一个问题,即响应不会与应用程序发送的命令同步。我认为这是特定于硬件的,但令我惊讶的是,当我通过将putty连接到相同端口的相同硬件时看到响应时,我可以看到响应始终是同步的。这看起来像腻子,使用一些标准将请求映射到响应。

以下是我用来向硬件设备发送命令的编程步骤: -

            Socket clientSocket = new Socket(<IPADDRESS>, 4001);
    DataOutputStream outToServer = new DataOutputStream(
            clientSocket.getOutputStream());
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
            clientSocket.getInputStream()));
    while (true) {
        try {
                            //Get command randomly from array enums for test
            Random r = new Random();
            Commands[] array = Commands.values();
            String command = (String) array[r
                    .nextInt(Commands.values().length)].getCommand();
            outToServer.writeBytes(command);
            Thread.sleep(500);
            while (!inFromServer.ready()) {
            }
            System.out.println("COMMAND "+command+", SERVER RESPONSE: "
                    + inFromServer.readLine());
            Thread.sleep(1500);

        } catch (SocketTimeoutException se) {
            //Handle Exception
        } catch (SocketException se) {
            //Handle Exception
        }

任何人都可以建议如何将响应与请求同步作为putty这样的机制来实现?

2 个答案:

答案 0 :(得分:1)

Putty对您的设备不再了解。问题出在您的代码中。摆脱ready()测试和sleep()。如果您可以确定设备发送了线路,请致电readLine(),否则只需拨打InputStream.read().

答案 1 :(得分:1)

删除线程睡眠,并重写如下:

String line;
while ((line = inFromServer.readLine()) != null) {
    System.out.println("COMMAND "+command+", SERVER RESPONSE: "
                + line);
}

如果设备发送的最后一条消息没有换行符\n,则此代码仍然可以挂起。您的原始代码跳过了输入。

主要问题在于这一行:

 while (!inFromServer.ready()) { 

InputStreamReader#ready只有在您有其他方式知道所有数据都已发送时才可以使用

  

判断此流是否已准备好进行读取。如果输入缓冲区不为空,或者可以从基础字节流中读取字节,则InputStreamReader就绪。

第一条消息将被读取,但会清空缓冲区,当第二条消息到达时,您的代码不再读取。你必须拥有与来自设备的消息一样多的循环,这至少是不切实际的。在这种情况下,它可能不会一直有效。

另一方面BufferedReader#readLine

  

<强>返回:

     

包含行内容的字符串,不包括任何行终止字符;如果已到达流末尾,则 null

将读取已读取所有已发送的数据。但是如果你的设备没有发送新的行字符,那么这个方法永远不会读取该行 - 代码将挂起缓冲区中的所有数据。在这种情况下,您应该使用InputStreamReader#read作为EJP建议:

  

<强>返回:

     

字符读取,或 -1,如果已到达流的末尾

我强烈建议您阅读IO Streams官方教程。

一般来说,等待不是由Thread.sleepbusy waiting(执行空语句)完成的,例如:

while (true) {}  /*or*/ while(true);

CPU正在执行空语句,它可能正在做一些其他工作,等待这一个完成。这是一种不好的做法。

如果您想了解有关如何实施等待的更多信息,建议您阅读official concurrency tutorialthis one,了解有关此问题的更广泛方法。