java - 如何仅使用标准网络库发送 HTTP 响应?

标签 java sockets response

我正在 Web 编程类(class)中完成我的第一个作业项目,即用 Java 编写一个简单的 Web 服务器。我正处于来回传输数据的阶段,在未经训练的人看来,我的小型服务器似乎工作正常。但是,我找不到发送适当回复的方法。 (换句话说,无效的页面请求将显示 404 左右的 HTML 页面,但当我查看响应 header 时它仍然返回 200 OK 状态)。

我只能使用标准网络库进行套接字管理,并使用标准 I/O 库从输入流读取和写入字节和字符串。这是一些相关代码:

从我的主要...

            ServerSocket servSocket = new ServerSocket(port, 10);           // Bind the socket to the port
        System.out.println("Opened port " + port + " successfully!");

                while(true) {
            //Accept the incoming socket, which means that the server process will
            //wait until the client connects, then prepare to handle client commands
            Socket newDataSocket = servSocket.accept();
            System.out.println("Client socket created and connected to server socket...");

            handleClient(newDataSocket);                                //Call handleClient method
        }   

来自handleClient方法...(在解析请求方法和路径的循环内)

                    if(checkURL.compareTo("/status") == 0)  {   // Check to see if status page has been requested
                    System.out.println("STATUS PAGE");      // TEMPORARY. JUST TO MAKE SURE WE ARE PROPERLY ACCESSING STATUS PAGE
                    sendFile("/status.html", dataStream);
                }
                else {
                    sendFile(checkURL, dataStream);         // If not status, just try the input as a file name
                }

从 sendFile 方法...

        File f = new File(where);                                               // Create the file object
    if(f.exists() == true) {                                                        // Test if the file even exists so we can handle a 404 if not.
        DataInputStream din;
        try {
            din = new DataInputStream(new FileInputStream(f));
            int len = (int) f.length();                                     // Gets length of file in bytes
            byte[] buf = new byte[len];
            din.readFully(buf);
            writer.write("HTTP/1.1 200 OK\r\n");                            // Return status code for OK (200)
            writer.write("Content-Length: " + len + "\r\n");                // WAS WRITING TO THE WRONG STREAM BEFORE!
            writer.write("Content-Type: "+type+"\r\n\r\n\r\n");             // TODO VERIFY NEW CONTENT-TYPE CODE
            out.write(buf);                                                 // Writes the FILE contents to the client
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();                                            // Not really handled since that's not part of project spec, strictly for debug.
        }
    }
    else {
        writer.write("HTTP/1.1 404 Not Found\r\n");                         // Attempting to handle 404 as simple as possible.
        writer.write("Content-Type: text/html\r\n\r\n\r\n");
        sendFile("/404.html", sock);
    }

任何人都可以解释一下,在 sendFile 的条件中,我可以如何更改 404 block 中的响应(就像我之前所说,响应 header 仍然显示 200 OK)?这让我很烦恼,我只想使用 HTTPResponse 类,但我不能。 (此外,如果 f.exists == true,则不会显示内容长度和类型。)

谢谢!

最佳答案

编辑在我看来,在 404 情况下,您发送的内容如下:

HTTP/1.1 404 Not Found
Content-Type: text/html
HTTP/1.1 200 OK
Content-Length: 1234
Content-Type: text/html

...后面是 404 页面。请注意 404 后面的 200 行。这是因为您的 404 处理正在调用 sendFile,它输出 200 响应状态代码。这可能会让接收者感到困惑。

错过了这一点的旧答案:

HTTP 响应以状态行开始,后跟(可选)一系列 header ,然后(可选)包含响应正文。状态行和标题只是定义格式的行,例如(随机选择一个示例):

HTTP/1.0 404 Not Found

要实现小型 HTTP 服务器,我建议通读 the spec并查看响应应该是什么样子。这有点概念上的飞跃,但它们实际上只是根据商定的格式返回的文本行。 (嗯,无论如何,几年前这对我来说是一个概念上的飞跃。我已经习惯了事情过于复杂的环境。)

从您最喜欢的命令行执行类似的操作也很有帮助:

telnet www.google.com 80
GET /thispagewontbefound

...然后按 Enter 键。你会得到这样的结果:

HTTP/1.0 404 Not Found
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sun, 12 Sep 2010 23:01:14 GMT
Server: sffe
Content-Length: 1361
X-XSS-Protection: 1; mode=block

...后面跟着一些 HTML 以提供友好的 404 页面。上面的第一行是状态行,其余的是标题。状态行/标题和第一行内容(例如页面)之间有一个空行。

关于java - 如何仅使用标准网络库发送 HTTP 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3696986/

相关文章:

java - 如何在 Jetty 上运行的 ReSTLet 应用程序中使用自定义 SSLContextFactory?

java - Java 8 默认接口(interface)中 `this` 的静态类型是什么?

java - JMenuitem加速器如何国际化?

c - UNIX 域套接字在 close() 后未关闭

Delphi — TClientSocket ReceiveText MaxLen?

javascript - 如何记录来自 fetch api 的响应

java - 保存实体然后排队到 RabbitMQ 的模式

python - before_request 的响应

node.js - 在nodejs中如何在请求中向服务器发送cookie

c++ - 如何使用 ZeroMQ 为两个发布者使用同一个端口向同一个订阅者发送数据?