【问题标题】:TCP/IP Client : best way to read multiple inputstreams from serverTCP/IP 客户端:从服务器读取多个输入流的最佳方式
【发布时间】:2016-04-22 18:47:31
【问题描述】:

我正在创建一个 java 客户端程序,它向服务器发送命令,服务器发回确认和响应字符串。

以这种方式发回响应

客户端 -> 服务器:cmd_string

服务器 -> 客户端:ack_msg(06)

服务器 -> 客户端:response_msg

当我尝试读取输入时,我只能通过一个输入流读取确认消息

我的客户端程序能够以某种方式读取消息(hacky 方法)。要读取输入,我必须使用 Bufferedreader 读取 ack msg。

  1. 此缓冲读取器只能读取 ack_msg 而不能读取以下 msg
  2. 需要DataInputstream代码来读取响应消息。
  3. 如果我跳过第 1 步而只使用 Datainputstream,我将无法读取完整的消息。

Client.java

try {
            Socket clientSocket = new Socket(SERVER_ADDRESS, TCP_SERVER_PORT);// ip,port

            System.out.println(" client Socket created .. ");
            
            PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(), true);

            String ToServer = command;
            outToServer.println(ToServer);

            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//          
            // while (!in.ready()) {
            // }
            System.out.println(in.read()); // Read one line and output it

            
            // ===
            byte[] messageByte = new byte[1000];//assuming msg size -need to know eact msg size ?
            boolean end = false;
            String dataString = "";
            int bytesRead = 0;

            try {
                DataInputStream in1 = new DataInputStream(clientSocket.getInputStream());
//
                while (!end) {
                    bytesRead = in1.read(messageByte);
                    dataString += new String(messageByte, 0, bytesRead);
                    if (dataString.length() > 0) {
                        end = true;
                    }
                }
                System.out.println("MESSAGE: " + dataString);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // ===
                
            in.close();             

            clientSocket.close();
            System.out.print("connection closed");

        } catch (Exception e) {
            System.out.print("Whoops! It didn't work!\n");
            e.printStackTrace();
        }

输出

已创建客户端 Socket ..

回复:6

消息:³CO³0³Œ

连接关闭

当我跳过第 1 步时

已创建客户端 Socket ..

消息:-

连接关闭

如何编写读取所有输入的代码 服务器(确认消息和响应消息,它还应该检查 数据的大小并相应地读取)?

参考How to read all of Inputstream in Server Socket JAVA

谢谢

【问题讨论】:

    标签: java sockets tcp client


    【解决方案1】:

    这些语句强制在发送至少 1 个字节后立即关闭流。

    dataString += new String(messageByte, 0, bytesRead);
    if (dataString.length() > 0) {
       end = true;
    }
    

    一旦收到 6 的 ack,连接就会关闭。如果 ack 被忽略,响应可能会分多个包发送,收到第一个包后连接会关闭。

    您必须能够确定 ack 和响应何时结束。

    1. 如果您知道 ack 和 response 中有多少个字符,您可以像您提到的问题一样循环。您将需要一个用于 ack 的循环和一个用于响应的循环。
    2. 如果您不知道 字符,那么您将不得不寻找特殊字符,例如 end-of-line 或 end-of-file 以知道 ack 行何时结束以及何时结束 服务器响应结束。为每条消息的结尾寻找一个特殊字符。
    3. 第三种可能性是等待 具体时间。时间到了,继续。这在 TCP 上是不可靠的,因为数据可能会丢失和重新发送。回复所需的时间可能比您分配的要长。我同意下面的评论。最初,我犹豫要不要在列表中添加 3。此选项很可能用于检测通信通道的问题。如果时间到了,那么客户端将放弃错误条件,它不会继续处理,就好像一切正​​常。

    【讨论】:

    • 我只想从这个答案中删除 (3)。它真的行不通。您无法预测服务器的延迟或服务时间。
    【解决方案2】:

    您不能在同一个底层套接字上同时使用 BufferedReader 和 DataInputStream。您将丢失 BufferedReader 中的数据。对所有内容以及套接字的生命周期都使用相同的流或读取器。编写器和输出流同上。

    【讨论】:

      【解决方案3】:
      InputStream input = null;
      OutputStream output = null;
      
      Socket cs = new Socket("LocalHost", 6789);
       input = cs.getInputStream();
      output = cs.getOutputStream();
       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(output));
      
      bw.write("Send your String");
      bw.flush();
      
      int bytesRead = 0;
      byte[] messageByte = new byte[1000];
      String dataString = "";
      
      bytesRead = input.read(messageByte);
      dataString = new String(messageByte, 0, bytesRead);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        • 1970-01-01
        • 2013-03-02
        • 2018-12-30
        相关资源
        最近更新 更多