java 为什么套接字的InputStream只有在套接字关闭时才返回-1?

rqdpfwrv  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(104)

我读过一些关于StackOverflow的问题,我们通常使用条件(c = inputStream.read()) == -1)来检测是否到达“流的结尾”。然而,我也读到过,如果套接字关闭,套接字的OutputStream只发送“流结束”消息。
这使得这个服务器代码。。

public class Server {
    public static int port = 27018;

    public static void main(String[] args) throws IOException, InterruptedException {
        char c = ' ';

        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("Server started");
        Socket connectionSocket = serverSocket.accept();
        serverSocket.close();
        String bufferOuputString = "";

        InputStream in = connectionSocket.getInputStream();
        OutputStream out = connectionSocket.getOutputStream();

        System.out.println("Connection established on port " + port);
        out.write("Welcome to my server !".getBytes());

        System.out.println("Waiting for client messages");
        while(c != '/'){
            c = (char) in.read();
            if(c == '*'){
                System.out.println(bufferOuputString);
                bufferOuputString = "";
            } else {
                bufferOuputString += c;
            }
        }

        connectionSocket.close();
    }
}

。。。和这个客户代码一起。。

public class Client {
    public static int port = 27018;

    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket("127.0.0.1", port)) {
            int c;
            Scanner sc = new Scanner(System.in);
            String bufferInputString = "";
            String bufferString = "";

            OutputStream out = socket.getOutputStream();
            InputStream in = socket.getInputStream();

            while((c = in.read()) != -1){
                bufferInputString += (char) c;
            }
            System.out.println(bufferInputString);

            while(!bufferString.contains("/")){
                System.out.println("You can write messages to server:");
                bufferString = sc.nextLine() + "*";
                out.write(bufferString.getBytes());
            }
        }
    }

}

没用因为客户端等待流结束信号(in.read() = -1),而这个信号永远不会到来,所以它一直被InputStream.read()调用阻塞。
为了记录在案,我尝试将其作为服务器代码来进一步检查套接字的“规则”:

public class Server {
    public static int port = 27018;

    public static void main(String[] args) throws IOException, InterruptedException {
        char c = ' ';

        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("Server started");
        Socket connectionSocket = serverSocket.accept();
        serverSocket.close();
        String bufferOuputString = "";

        InputStream in = connectionSocket.getInputStream();
        OutputStream out = connectionSocket.getOutputStream();

        System.out.println("Connection established on port " + port);
        out.write("Welcome to my server !".getBytes());
        Thread.sleep(3000);
        connectionSocket.close();
    }
}

3秒钟后,客户端打印出...

...然后进入无限循环,因为我忘记更改第二个while循环。因此,这确认了套接字的OutputStream对象只在Socket.close()处发送“流结束”。我的问题是:为什么选择这种设计?

uz75evzq

uz75evzq1#

  • 我还读到,如果套接字关闭,套接字的OutputStream只会发送“流结束”消息。

不是默认的。
Socket 类中似乎没有任何东西会传输 -1 值。
这里是 Socket#close 的源代码,这里是 ServerSocket#close
-1 到达数据流的末尾时,由 read 方法发送。
因此,它将取决于接口-例如,* FTP * 使用 \r\n 序列来表示传输的结束。
这个概念是为了增加组件之间的一致性,因为数据传输是“昂贵的”。
此外,它类似于 HTTP 头包含 content-length 的方式-这减少了,一些人称之为 * polling *-本质上,while((c = in.read())!= -1),没有块。

  • Blocking * 是一个更符合逻辑的概念,以避免需要 poll
  • ...因为客户端在等待流结束信号(in.read()= -1),而这个信号永远不会到来,所以它一直被InputStream.read()调用阻塞。*

正确。Socket 正在访问 SocketInputStream#read 方法,如果没有数据,该方法将阻塞。

相关问题