如何修复Broken Pipe Socket Exception(Java)?连接在哪里关闭?

时间:2019-10-29 17:38:21

标签: java sockets http server

我正在为学校项目使用多线程Web服务器。我应该能够在浏览器中进入localhost并请求3个不同的文件(.htm,.jpeg,.pdf)。但是,当我对同时包含图片的.htm文件执行此操作时(2个请求),该.htm文件出现在浏览器中,但是每次尝试在图片上执行写入操作时,我都会遇到很多管道异常的异常(分配要求一次写入1024个字节)。我实现此方法的方式显然出了问题,但是当我尝试为第二个文件编写时,我对连接在何处关闭感到迷茫?

我尝试了几种不同的方法来尝试解决此问题,包括在尝试读取套接字输入流时进行循环,但是我认为这样做违反了多线程服务器的目的。

服务器:

    while(true){
        try {
            sock = servSock.accept(); // Handles the connection
            // Connection received log
            System.out.println("Connection received: " + new Date().toString() + " at " + sock.getInetAddress() + sock.getPort());
            HTTP pro = new HTTP(sock); // Client handler
            pro.run();

            ServerThread serverThread = new ServerThread(pro); 
            // Starts ServerThread
            serverThread.start();
        } catch (Exception e){
            System.out.println(e);
        }
    }

HTTP:


    public void run(){
        // Try to open reader
        try{
            readSock = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        } catch (Exception e){
            System.out.println(e);
        }

        // Open output stream
        try{
            this.out = new DataOutputStream(sock.getOutputStream()); 
            this.printOut = new PrintWriter(sock.getOutputStream()); 
        } catch (Exception e){
            System.out.println(e);
        }

        // Try to read incoming line
        try {
            this.reqMes = readSock.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        StringTokenizer st = new StringTokenizer(reqMes);

        // Parse the request message
        int count = 0;
        while(st.hasMoreTokens()){
            String str = st.nextToken();
            if (count == 1){
                this.fileName = "." + str;
            }
            count += 1;
        }
        System.out.println("File name received.");

        File file = null;
        try {
            file = new File(this.fileName);
            this.f = new FileInputStream(file); // File input stream
            this.fileExists = true;
            System.out.println("File " + this.fileName +  " exists.");
        } catch (FileNotFoundException e) {
            System.out.println(e);
            this.fileExists = false;
            System.out.println("File does not exist.");
        }

        byte[] buffer = new byte[1024];
        // Write status line
        if (this.fileExists) {
            System.out.println("Trying to write data");
            try{
                this.out.writeBytes("HTTP/1.0 " + "200 OK " + this.CRLF);
                this.out.flush();
                this.printOut.println("HTTP/1.0 " + "200 OK " + this.CRLF);
                // Write Header
                this.out.writeBytes("Content-type: " + getMime(this.fileName) + this.CRLF);
                this.printOut.println("Content-type: " + getMime(this.fileName) + this.CRLF);
                this.out.flush();

                // Read file data
                byte[] fileData = new byte[1024];

                while (this.f.read(fileData) != -1) {
                    // Write File data
                    try{
                        this.out.write(fileData,0,1024);
                        this.out.flush(); // Flush output stream
                    } catch (IOException e) {
                        System.out.println(e);
                    }
                }
                System.out.println("Flushed");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

对于浏览器中的一个.htm文件,该文件和html看起来似乎不错。但是看起来它再次请求html文件中的.jpeg文件,并且浏览器陷入了用java.net.SocketException加载的麻烦:每次在

处写入数据时,管道损坏(写入失败)。
this.out.write(fileData,0,1024);

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

在对不同问题进行了大量搜索之后,我找到了答案here

问题在于响应头的格式不正确,导致连接过早终止。 必须在标头之后发送另一个空行(“ \ r \ n”)。

以下代码现在有效(this.CRLF等于“ \ r \ n”):

    public void run(){
        // Try to open reader
        try{
            readSock = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        } catch (Exception e){
            System.out.println(e);
        }

        // Open output stream
        try{
            this.out = new DataOutputStream(sock.getOutputStream()); // Data output
            this.printOut = new PrintWriter(sock.getOutputStream()); // Print output
        } catch (Exception e){
            System.out.println(e);
        }

        // Try to read incoming line
        try {
            this.reqMes = readSock.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        StringTokenizer st = new StringTokenizer(reqMes);

        // Parse the request message
        int count = 0;
        while(st.hasMoreTokens()){
            String str = st.nextToken();
            if (count == 1){
                this.fileName = "." + str;
            }
            count += 1;
        }
        System.out.println("File name received.");

        // Initialize file to be sent
        File file = null;
        // Try to find file and create input stream
        try {
            file = new File(this.fileName);
            this.f = new FileInputStream(file); // File input stream
            this.fileExists = true;
            System.out.println("File " + this.fileName +  " exists.");
        } catch (FileNotFoundException e) {
            System.out.println(e);
            this.fileExists = false;
            System.out.println("File does not exist.");
        }

        byte[] buffer = new byte[1024];
        // Write status line
        if (this.fileExists) {
            System.out.println("Trying to write data");
            try{
                this.out.writeBytes("HTTP/1.0 " + "200 OK " + this.CRLF);
                this.out.flush();
                // Write Header
                this.out.writeBytes("Content-type: " + getMime(this.fileName) + this.CRLF);
                this.out.flush();
                this.out.writeBytes(this.CRLF);
                this.out.flush();

                // Read file data
                byte[] fileData = new byte[1024];

                int i;
                while ((i = this.f.read(fileData)) > 0) {
                    // Write File data
                    try{
                        this.out.write(fileData,0, i);
                    } catch (IOException e) {
                        System.out.println(e);
                    }
                }
                this.out.flush(); // Flush output stream
                System.out.println("Flushed");
                closeSock(); // Closes socket
            } catch (IOException e) {
                e.printStackTrace();
            }