0

我正在尝试修复一个 java 套接字通信错误,其中服务器不知道输入消息的长度。在当前情况下,服务器测试输入是否使用inputStream.available();方法完成。然而,这种方法并不总是返回正确的答案。它会导致读取部分输入。似乎有两种不同的可能性来解决这个问题。

  1. 客户端应发送输入大小。

  2. 客户端应该在发送后关闭它的输出流,但它会导致客户端无法读取响应,因为当输出流关闭时套接字也关闭了。

还有其他建议吗,尤其是在 nio 软件包的帮助下?

谢谢你。

4

4 回答 4

1

您可以使用

socket.shutdownOutput();

关闭客户端的输出流。这将显示为关闭的输入流,而不关闭套接字。

顺便说一句:你不能socket.getOuputStream().close();像我一样使用。

恕我直言,发送长度是最好的选择,因为这将允许您使用同一个套接字发送多个请求。


这是一个例子

public class SimpleServerMain {
    public static void main(String... args) throws IOException, InterruptedException {
        ServerSocket ss = new ServerSocket(54321);
        Socket s = ss.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
        for (String line; (line = br.readLine()) != null; )
            System.out.println("Got " + line);

        PrintStream ps = new PrintStream(s.getOutputStream());
        for (String word : "Hello World Bye Bye!".split(" ")) {
            ps.println(word);
            Thread.sleep(1000);
        }
        s.close();
        ss.close();
    }
}

public class SimpleClientMain {
    public static void main(String... args) throws IOException {
        Socket s = new Socket("localhost", 54321);
        InputStream inputStream = s.getInputStream();

        s.getOutputStream().write("Hello\n".getBytes());
        s.shutdownOutput();

        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        for (String line; (line = br.readLine()) != null; )
            System.out.println("Got " + line);
        System.out.println("Disconnected.");
        s.close();
    }
}
于 2013-05-31T10:20:45.090 回答
1

available()不是消息长度的度量,因此如果您对“正确答案”的定义是“消息长度”,则没有理由返回“正确答案”。

如果你想要一个消息长度,你必须发送一个。或者使用行,或者像 XML、序列化等自描述协议。

于 2013-05-31T11:15:13.583 回答
0

Imo,发送输入大小似乎是处理这个问题的最好方法,但你也可以尝试为每条消息定义一个固定的消息长度和一个 ID。

您只需将消息拆分为您选择的大小的部分。
收到新消息时,您只需检查 id 是否与前一个相同。如果是,则将新消息附加到第一条消息的末尾。如果不是,您可以对上一条消息执行您想要执行的操作,然后开始录制新消息。
每次发送消息的所有部分时,客户端都会发送一条特殊消息来表示它已完成。

于 2013-05-31T10:25:00.617 回答
0

至少还有另外两种未提及的方法可能应该是。

  1. 使用特殊字符表示某个输入的结束。如果输入中不允许有新行,\r\n则可以选择。

  2. 使用某种序列化 - 您可以将数据作为 JSON 对象或 XML 左右发送,然后您会知道什么时候没有更多数据。

于 2013-05-31T10:28:52.460 回答