Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 输入长度未知的套接字通信_Java_Sockets_Client Server - Fatal编程技术网

Java 输入长度未知的套接字通信

Java 输入长度未知的套接字通信,java,sockets,client-server,Java,Sockets,Client Server,我试图修复一个java套接字通信错误,服务器不知道输入消息的长度。在当前情况下,服务器测试输入是否使用inputStream.available()完成方法。然而,这种方法并不总是返回正确的答案。它会导致读取部分输入。解决这个问题似乎有两种不同的可能性 客户端应发送输入大小 客户端应该在发送后关闭其输出流,但这会导致客户端不读取响应,因为输出流关闭时套接字也会关闭 还有其他建议吗,特别是在nio包的帮助下 谢谢。您可以使用 socket.shutdownOutput(); 关闭客户端的输出流。

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

  • 客户端应发送输入大小

  • 客户端应该在发送后关闭其输出流,但这会导致客户端不读取响应,因为输出流关闭时套接字也会关闭

  • 还有其他建议吗,特别是在nio包的帮助下

    谢谢。

    您可以使用

    socket.shutdownOutput();
    
    关闭客户端的输出流。这将显示为关闭的输入流,而不关闭套接字

    顺便说一句:您不能使用
    socket.getOutStream().close()我认为你可以

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


    这里有一个例子

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


    在我看来,发送输入大小似乎是解决这一问题的最佳方法,但您也可以尝试为每条消息定义固定的消息长度和ID

    您只需将邮件拆分为您选择的大小部分。
    收到新邮件时,您只需检查id是否与前一条相同。如果是,则将新消息附加到第一条消息的末尾。如果不是,您可以对上一条消息执行您想执行的操作,然后开始录制新消息。

    每次发送完消息的所有部分后,客户机都会发送一条特殊消息,表示消息已完成。

    至少还有两种方法没有提及,可能应该提及

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

  • 使用某种序列化—您可以将数据作为JSON对象或XML等形式发送,这样您就知道什么时候没有更多的数据了

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


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

    感谢您的快速响应,我已尝试在客户端关闭inputstream,但这也会导致连接关闭。因此,关闭inputstream后,客户端无法读取响应,因为套接字已关闭。关闭输出流不必关闭连接,但某些库可能会这样做。如果他们这样做了,那就是一个错误。只有一端将插座关闭,插座才会关闭。如果您正在使用一个在您不知情的情况下关闭套接字的库,我建议您使用另一个库。我认为这是默认行为。但我将尝试socket.shutdownInput()。这是链接。但是你说socket.getOutputStream().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();
        }
    }