TCP/IP 客户端:从服务器读取多个输入流的最佳方式

TCP/IP Client : best way to read multiple inputstreams from server

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

The response is sent back in this manner

client -> server : cmd_string

server -> client : ack_msg(06)

server -> client : response_msg

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

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

读取确认消息
  1. 这缓冲 reader 只能读取 ack_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();
        }

输出

客户端套接字已创建..

响应:6

消息:³CO³0³Œ

连接关闭

当我跳过第 1 步时

客户端套接字已创建..

留言:-

连接关闭

How can I write code that reads all the input from server(acknowledgement msg & response message & it should also check the size of data and read accordingly)?

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

谢谢

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

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

一旦收到 6 的确认,连接就会关闭。如果忽略ack,响应可能会在多个数据包中发送,连接将在收到第一个数据包后关闭。

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

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

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

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