简体   繁体   English

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

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

I am attempting to read an input stream from a socket provided by a web browser client.我正在尝试从 web 浏览器客户端提供的套接字读取输入 stream。 Every approach I have taken has got the same results thus far, it just hangs and I don't know why.到目前为止,我采取的每种方法都得到了相同的结果,它只是挂起,我不知道为什么。 I have tried mark() marking the read limit to what is available and still no go.我已经尝试使用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();

I have also tried clientSocket.shutdownInput() to tried to fix this issue, still no good.我也尝试过clientSocket.shutdownInput()来尝试解决这个问题,但还是不行。

Here is my attempt below:以下是我的尝试:

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

Any help would be most appreciated.非常感激任何的帮助。 Thank you.谢谢你。

browsers suggests you should toss this all in the garbage and use HTTP, because, well, browsers. browsers 建议您应该将所有这些都扔进垃圾箱并使用 HTTP,因为,嗯,浏览器。

But, if you insist, there are two problems here.但是,如果你坚持,这里有两个问题。

  1. You've made it crazy complicated.你把事情搞的很复杂。

You can take all of that code and replace it all with this simple little line:您可以使用所有这些代码并将其全部替换为以下简单的小行:

byte[] bytes = in.readAllBytes();

That replaces the lines starting with in.mark(in.available()) (this line does nothing at all, I have no idea where you got this from. If you think it is supposed to do something specific, you might want to mention that. Because it doesn't do anything. mark is useful if you ever reset , which you aren't, and you don't need to here, hence, useless), all the way to `byte[] bytes =...;这取代了以in.mark(in.available())开头的行(这条线什么都不做,我不知道你从哪里得到的。如果你认为它应该做一些特定的事情,你可能想提一下那。因为它什么也没做。如果你曾经resetmark是有用的,你不是,你不需要在这里,因此,没用),一直到`byte [] bytes =.. .;

  1. sockets don't close unless sender goes out of its way to close it sockets 不会关闭,除非发件人竭尽全力关闭它

Your read code (yours, or the much simpler one-liner above) reads everything until the stream closes.您的读取代码(您的,或者上面更简单的单行代码)读取所有内容,直到 stream 关闭。 In your second snippet, you close it right away, which obviously doesn't work.在您的第二个片段中,您立即将其关闭,这显然不起作用。 You cannot know when to close it, the sender does this job.知道什么时候关闭它,发件人完成这项工作。 Evidently it's not doing it.显然它没有这样做。

I advise you to adapt protocols that pre-roll sizes, so you know how much to read and aren't dependent on closing the socket just to signal that the data is sent.我建议您调整预滚动大小的协议,这样您就知道要读取多少,而不是仅仅依靠关闭套接字来发出数据已发送的信号。

For example:例如:

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

You will of course have to adjust the sending code to send the size first (as a 32-bit value, big endian).您当然必须调整发送代码以首先发送大小(作为 32 位值,大端)。 One way or another you have to look at the sending code here.您必须以一种或另一种方式查看此处的发送代码。 Either fix it so that it closes once done, or, better yet, adjust it so it sends size first.要么修复它,让它在完成后关闭,或者更好的是,调整它,让它首先发送大小。

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

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