繁体   English   中英

尝试从 web 浏览器 Java 读取输入 stream 时,套接字挂起

[英]Socket hangs when trying to read input stream from web browser Java

我正在尝试从 web 浏览器客户端提供的套接字读取输入 stream。 到目前为止,我采取的每种方法都得到了相同的结果,它只是挂起,我不知道为什么。 我已经尝试使用mark()将读取限制标记为可用但仍然没有 go。

inputStream.mark(inputStream.available());

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 9];
int read;

while((read = inputStream.read(buffer)) > 0) {
    outputStream.write(buffer, 0, read);
}
byte[] bytes = outputStream.toByteArray();

我也尝试过clientSocket.shutdownInput()来尝试解决这个问题,但还是不行。

以下是我的尝试:

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Server {
    public static void main(String[] args)
    {
        ServerSocket server = null;

        try {

            // Server is listening on port 3001
            server = new ServerSocket(3001, 1, InetAddress.getByName("localhost"));
            server.setReuseAddress(true);

            // running infinite loop for getting
            // client request
            while (true) {

                // socket object to receive incoming client
                // requests
                Socket client = server.accept();

                // Displaying that new client is connected
                // to Server
                System.out.println("New client connected"
                        + client.getInetAddress()
                        .getHostAddress());


                // create a new thread object
                ClientHandler clientSock
                        = new ClientHandler(client);

                // This thread will handle the client
                // separately
                new Thread(clientSock).start();

            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    // ClientHandler class
    private static class ClientHandler implements Runnable {

        private final Socket clientSocket;

        // Constructor
        public ClientHandler(Socket clientSocket)
        {
            this.clientSocket = clientSocket;
        }

        public void run() {


            InputStream inputStream = null;
            OutputStream clientOutput = null;
            try {

                inputStream = clientSocket.getInputStream();
                inputStream.mark(inputStream.available());

                clientSocket.shutdownInput();

                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024 * 9];
                int numRead;

                while((numRead = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, numRead);
                }

                byte[] bytes = outputStream.toByteArray();

                String payloadString = new String(bytes, StandardCharsets.UTF_8);
                System.out.println(payloadString);

                clientOutput = clientSocket.getOutputStream();
                clientOutput.write(("HTTP/1.1 \r\n" + "200 OK").getBytes());
                clientOutput.write(("ContentType: " + "text/html" + "\r\n").getBytes());
                clientOutput.write("\r\n".getBytes());
                clientOutput.write("Hello World!".getBytes());
                clientOutput.write("\r\n\r\n".getBytes());
                clientOutput.flush();
                inputStream.close();
                clientOutput.close();
                try{
                    clientSocket.close();
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

非常感激任何的帮助。 谢谢你。

browsers 建议您应该将所有这些都扔进垃圾箱并使用 HTTP,因为,嗯,浏览器。

但是,如果你坚持,这里有两个问题。

  1. 你把事情搞的很复杂。

您可以使用所有这些代码并将其全部替换为以下简单的小行:

byte[] bytes = in.readAllBytes();

这取代了以in.mark(in.available())开头的行(这条线什么都不做,我不知道你从哪里得到的。如果你认为它应该做一些特定的事情,你可能想提一下那。因为它什么也没做。如果你曾经resetmark是有用的,你不是,你不需要在这里,因此,没用),一直到`byte [] bytes =.. .;

  1. sockets 不会关闭,除非发件人竭尽全力关闭它

您的读取代码(您的,或者上面更简单的单行代码)读取所有内容,直到 stream 关闭。 在您的第二个片段中,您立即将其关闭,这显然不起作用。 知道什么时候关闭它,发件人完成这项工作。 显然它没有这样做。

我建议您调整预滚动大小的协议,这样您就知道要读取多少,而不是仅仅依靠关闭套接字来发出数据已发送的信号。

例如:

byte[] sizeRaw = in.readNBytes(4);
int size = ByteBuffer.wrap(bytes).getInt();
byte[] bytes = in.readNBytes(size);

您当然必须调整发送代码以首先发送大小(作为 32 位值,大端)。 您必须以一种或另一种方式查看此处的发送代码。 要么修复它,让它在完成后关闭,或者更好的是,调整它,让它首先发送大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM