Java 带有响应代码的 TCP 简单 Web 服务器问题(作业)

Java TCP Simple Webserver Problems with response codes (homework)

这是我们正在上的课程的作业,我需要一些帮助。

我遇到了一些问题,例如,尝试请求一个不存在的文件,出现 404 文件未找到页面是有效的,但是当我查看 Safari 的网络工具时,我可以看到响应code is 200, OK, definialty wrong,应该是错误的代码。

但为什么我没有看到,当发生错误时我发送错误代码 header,但它仍然不起作用。有人可以指出正确的方向,或者只是说出问题所在,我可以解决它 :D 吗?

主要:

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;

public class WebServer {

    private static int PORT = 8888;
    private static String ROOT_DIR = "";

    public static void main(String[] args) {


        if (isCorrect(args) == true) {

            boolean isRunning = true;

            try {

            /* Creates a new server socket */
                ServerSocket serverSocket = new ServerSocket();

            /* Binds the port to the server */
                SocketAddress localBindPoint = new InetSocketAddress(PORT);

                serverSocket.bind(localBindPoint);

                System.out.println("==============================================" +
                        "\n| HTTP Web Server |" +
                        "\n===================" +
                        "\n| Configuration: " +
                        "\n| Directory: " +
                        "\n| " + ROOT_DIR +
                        "\n| Port: " +
                        "\n| " + PORT +
                        "\n| Usage: <directory> <port>" +
                        "\n| ctrl-c to exit" +
                        "\n==============================================");
            /* The server is running */
                while (isRunning) {

                    try {

                /* Accept connection by client */
                        Socket socket = serverSocket.accept();

                /* Each connected client gets a new thread */
                        new Thread(new RequestHandler(socket, ROOT_DIR)).start();

                    } catch (IOException e) {
                        System.err.println(e.getMessage());
                    }
                }
            } catch (IOException e) {
                System.err.println("Address already in use!" +
                        "\nClose running connection or choose other port");
            }
        } else
            usageMsg();
        System.exit(1);
    }

    public static boolean isDirectory(String path){
        File filePath = null;
        try{

            filePath = new File(path);
            /* False if file is not a directory */
            if (!filePath.isDirectory())
                return false;

        }
        catch (Exception e){
            System.err.println(e.getMessage());
        }
        /* Seems to be a file path */
        return true;
    }

    public static boolean isCorrect(String[] args){

        if (args.length != 2){
            usageMsg();
            return false;
        }

        try{
            ROOT_DIR = args[0].toString();
            PORT = Integer.parseInt(args[1]);
        }
        catch (NumberFormatException n){
            System.err.println(n.getMessage());
        }

        if (!isDirectory(ROOT_DIR)){
            usageMsg();
            return false;
        }

        return true;
    }

    public static void usageMsg(){
        System.err.println("Invalid arguments"+
                "\nUsage: java -jar Webserver.jar <directory> <port>");
    }
}

请求处理程序:

import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;

/**
 * Web Server Request Handler.
 * Created on 2015-02-16.
 */

public class RequestHandler implements Runnable {

    /*
    TODO ( ) Problem 1
    TODO ( ) Problem 2
    TODO ( ) Problem 3
    TODO (X) Index page for first page.
    TODO (X) Read and download images & other files
    TODO ( ) Fix header responses
    TODO ( ) Error responses
     */

    private String
            OK = "HTTP/1.0 200 OK",
            NOT_FOUND = "HTTP/1.0 404 Not Found",
            BAD_REQUEST = "HTTP/1.0 400 Bad Request",
            FORBIDDEN = "HTTP/1.0 403 Forbidden",
            SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";

    private String ROOT_DIR;
    private Socket client;
    private PrintStream send;
    private DataInputStream fromClient;
    private DataOutputStream out;

    RequestHandler(Socket client, String ROOT_DIR) {
        this.client = client;
        this.ROOT_DIR = ROOT_DIR;

        try {
            send = new PrintStream(client.getOutputStream());
            fromClient = new DataInputStream(client.getInputStream());
            out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));


        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    /* Reads the HTTP request and responds */
    public void run() {
        String request = null;
        String fileName = null;
        StringTokenizer tok = null;

        try {

            /* Read HTTP request from client */
            while ((request = fromClient.readLine()) != null) {

                System.out.println(request);
                tok = new StringTokenizer(request);

            /* Extracts the file path from the GET command */
                if (tok.hasMoreElements() && tok.nextToken().equals("GET")
                        && tok.hasMoreElements()) {

                    fileName = tok.nextToken();
                } else
                    throw new FileNotFoundException();

                /* */
                if (fileName.endsWith("/"))
                    fileName += "index.html";

                /* Illegal characters, prevent access to super directories */
                if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
                        || fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {

                    error(FORBIDDEN, "Forbidden Access", fileName);
                }
                else

                if (new File(fileName).isDirectory()) {
                    fileName = fileName.replace('\', '/');
                    send.close();
                    return;
                }

            /* File name is ROOT_DIR + file name */
                fileName = ROOT_DIR + fileName;

            /* Create file */
                File file = new File(fileName);

                if (file.isDirectory()) {
                    fileName = fileName + "index.html";
                }
            /* File does not exist */
                if (file.exists()){
            /* Determines the MIME type of the file */
                    String mimeType = getMimeType(file);

            /* Sends the file */
                    sendFile(file, mimeType, fileName);
                    client.close();
                }
                else
                    error(NOT_FOUND, "404 File Not Found", fileName);
            }

        }
        catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
        }
        catch (IOException e){
            System.err.println(e.getMessage());
        }
    }

    /* Sends the requested file to the client */
    public void sendFile(File file, String fileType, String fileName) {
        try {
            // Buffer must not be to low, => fragments
            int length = (int) file.length();
            FileInputStream fileIn = new FileInputStream(fileName);
            byte[] bytes = new byte[length];

            /* Write until bytes is empty */
            while ((length = fileIn.read(bytes)) != -1 ){
                out.write(bytes, 0, length);
                out.flush();
                out.writeBytes(OK);
                out.writeBytes("Server: Jakobs Web Server v1.0");
                out.writeBytes("Content-Type: " + fileType + "\r\n");
                out.writeBytes("Content-Length: " + length + "\r\n");
                out.writeBytes("");
            }
            send.close();
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    /* Sends the header response to the client */
    public void sendHeaderResponse(String code, String fileType){
        try {
            out.writeBytes(code);
            out.writeBytes("Server: Jakobs Web Server v1.0");
            out.writeBytes("Content-Type: " + fileType + "\r\n");
            out.writeBytes("");
        }
        catch (IOException e){
            System.err.println(e.getMessage());
        }
    }

    /* Sends error response to the client */
    public void error(String code, String error, String fileName){
        System.err.println(error +
                "\nFile Requested: " + fileName);

        /* Sends the error code header */
        sendHeaderResponse(code, fileName);

        /* Sends the error message and cause to client */
        send.print("<html><head><title>" + error + "</title></head><body>");
        send.print("<h1>" + error + "</h1>\r\n");
        send.println("Location: /" + fileName + "/\r\n");
        send.println("Exception Cause: " + error + "\r\n");
        send.print("<a href=\"index.html\">Start Page</a>");
        send.print("</body>\"</html>");
        send.flush();
        send.close();
    }

    /* Finds out the MIME type of the requested file */
    public String getMimeType(File f) {
        String file = f.toString();
        String type = "";
        if (file.endsWith(".txt")) {
            type = "text/txt";
        } else if (file.endsWith(".html") || file.endsWith("htm")) {
            type = "text/html";
        } else if (file.endsWith(".jpg")) {
            type = "image/jpg";
        } else if (file.endsWith(".png")) {
            type = "image/png";
        } else if (file.endsWith(".jpeg")) {
            type = "image/jpeg";
        } else if (file.endsWith(".gif")) {
            type = "image/gif";
        } else if (file.endsWith(".pdf")) {
            type = "application/pdf";
        } else if (file.endsWith(".mp3")) {
            type = "audio/mpeg";
        } else if (file.endsWith(".class")){
            type = "application/octet-stream";
        } else if (file.endsWith(".mp4")){
            type = "video/mp4";
        }
        return type;
    }
}

确保你写了例如HTTP/1.1 404 Not Found 给客户端,而不仅仅是 400

其实不是,你的问题是你没有正确结束响应。浏览器一直在接收数据,显示没有收到响应码。让我看看如何在您的代码中解决这个问题。

此外,您在 client.getOutputStream() 周围使用两个包装器流将数据发送到客户端(sendout)。不确定你为什么这样做。这看起来很奇怪。您应该只使用一个包装器流。而且你永远不会关闭 out,可能这就是你的问题,这就是浏览器认为响应尚未完全收到的原因。尝试使用一个流并正确处理它。

好的,您的代码已修复。

import java.io.*;
import java.net.Socket;
import java.util.StringTokenizer;

/**
 * Web Server Request Handler.
 * Created on 2015-02-16.
 */

public class RequestHandler implements Runnable {

    /*
    TODO ( ) Problem 1
    TODO ( ) Problem 2
    TODO ( ) Problem 3
    TODO (X) Index page for first page.
    TODO (X) Read and download images & other files
    TODO ( ) Fix header responses
    TODO ( ) Error responses
     */

    private String
            OK = "HTTP/1.0 200 OK",
            NOT_FOUND = "HTTP/1.0 404 Not Found",
            BAD_REQUEST = "HTTP/1.0 400 Bad Request",
            FORBIDDEN = "HTTP/1.0 403 Forbidden",
            SERVER_ERROR = "HTTP/1.0 500 Internal Server Error";

    private String ROOT_DIR;
    private Socket client;
    private PrintStream send;
    private DataInputStream fromClient;
    // private DataOutputStream out;

    RequestHandler(Socket client, String ROOT_DIR) {
        this.client = client;
        this.ROOT_DIR = ROOT_DIR;

        try {
            send = new PrintStream(client.getOutputStream());
            fromClient = new DataInputStream(client.getInputStream());
            // out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));


        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    /* Reads the HTTP request and responds */
    public void run() {
        String request = null;
        String fileName = null;
        StringTokenizer tok = null;

        try {

            /* Read HTTP request from client */
            while ((request = fromClient.readLine()) != null) {

                System.out.println(request);
                tok = new StringTokenizer(request);

            /* Extracts the file path from the GET command */
                if (tok.hasMoreElements() && tok.nextToken().equals("GET")
                        && tok.hasMoreElements()) {

                    fileName = tok.nextToken();
                } else
                    throw new FileNotFoundException();

                /* */
                if (fileName.endsWith("/"))
                    fileName += "index.html";

                /* Illegal characters, prevent access to super directories */
                if (fileName.indexOf("..") >= 0 || fileName.indexOf('|') >= 0
                        || fileName.indexOf(':') >= 0 || fileName.indexOf('~') >= 0) {

                    error(FORBIDDEN, "Forbidden Access", fileName);
                }
                else

                if (new File(fileName).isDirectory()) {
                    fileName = fileName.replace('\', '/');
                    send.close();
                    return;
                }

            /* File name is ROOT_DIR + file name */
                fileName = ROOT_DIR + fileName;

            /* Create file */
                File file = new File(fileName);

                if (file.isDirectory()) {
                    fileName = fileName + "index.html";
                }
            /* File does not exist */
                if (file.exists()){
            /* Determines the MIME type of the file */
                    String mimeType = getMimeType(file);

            /* Sends the file */
                    sendFile(file, mimeType, fileName);
                    client.close();
                }
                else
                    error(NOT_FOUND, "404 File Not Found", fileName);
            }

        }
        catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
        }
        catch (IOException e){
            System.err.println(e.getMessage());
        }
    }

    /* Sends the requested file to the client */
    public void sendFile(File file, String fileType, String fileName) {
        try {
            // Buffer must not be to low, => fragments
            int length = 0; // (int) file.length();
            FileInputStream fileIn = new FileInputStream(fileName);
            byte[] bytes = new byte[1024];
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            /* Write until bytes is empty */
            while ((length = fileIn.read(bytes)) != -1 ){
                bos.write(bytes, 0, length);
                // send.write(bytes, 0, length);
                // send.flush();
            }
            bos.flush();
            bos.close();
            byte[] data1 = bos.toByteArray();

            System.out.print(new String(data1));
            send.print(OK);
            send.print("");
            send.print("Server: Jakobs Web Server v1.0");
            send.print("Content-Type: " + fileType + "\r\n");
            send.print("Content-Length: " + data1.length + "\r\n");
            send.println("");
            send.write(data1, 0, data1.length);
            send.println("");

            send.flush();
            send.close();

            fileIn.close();

        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }

    /* Sends the header response to the client */
    public void sendHeaderResponse(String code, String fileType){
        try {
            send.print(code);
            send.print("Server: Jakobs Web Server v1.0");
            send.print("Content-Type: " + fileType + "\r\n");
            send.print("");
            send.println();
        }
        catch (Exception e){
            System.err.println(e.getMessage());
        }
    }

    /* Sends error response to the client */
    public void error(String code, String error, String fileName){
        System.err.println(error +
                "\nFile Requested: " + fileName);

        /* Sends the error code header */
        sendHeaderResponse(code, fileName);

        // send.println("ERROR");

        /* Sends the error message and cause to client */

        send.print("<html><head><title>" + error + "</title></head><body>");
        send.print("<h1>" + error + "</h1>\r\n");
        send.println("Location: /" + fileName + "/\r\n");
        send.println("Exception Cause: " + error + "\r\n");
        send.print("<a href=\"index.html\">Start Page</a>");
        send.print("</body></html>");

        send.flush();
        send.close();
    }

    /* Finds out the MIME type of the requested file */
    public String getMimeType(File f) {
        String file = f.toString();
        String type = "";
        if (file.endsWith(".txt")) {
            type = "text/txt";
        } else if (file.endsWith(".html") || file.endsWith("htm")) {
            type = "text/html";
        } else if (file.endsWith(".jpg")) {
            type = "image/jpg";
        } else if (file.endsWith(".png")) {
            type = "image/png";
        } else if (file.endsWith(".jpeg")) {
            type = "image/jpeg";
        } else if (file.endsWith(".gif")) {
            type = "image/gif";
        } else if (file.endsWith(".pdf")) {
            type = "application/pdf";
        } else if (file.endsWith(".mp3")) {
            type = "audio/mpeg";
        } else if (file.endsWith(".class")){
            type = "application/octet-stream";
        } else if (file.endsWith(".mp4")){
            type = "video/mp4";
        }
        return type;
    }
}