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

时间:2010-09-12 22:54:30

标签: java sockets response

我正在编写一个Web编程类的第一个家庭作业项目,即用Java编写一个简单的Web服务器。我正处于数据来回传输的地步,对于未经训练的眼睛,我的婴儿服务器似乎工作正常。但是,我找不到发送适当回复的方法。 (换句话说,无效页面请求将显示404-ish HTML页面,但在查看响应标头时仍会返回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块中的响应(就像我之前说的那样,响应头仍然显示200 OK)?这是我的废话,我只是想使用HTTPResponse类,但我不能。 (另外,如果f.exists == true,则不显示内容长度和类型。)

谢谢!

3 个答案:

答案 0 :(得分:3)

编辑在我看来,就像在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响应以状态行开始,后跟(可选)一系列标头,然后(可选)包括响应主体。状态行和标题只是定义格式的行,如(选择随机示例):

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页面。上面的第一行是状态行,其余的是标题。状态行/标题与第一行内容(例如页面)之间有一个空行。

答案 1 :(得分:2)

您看到的问题很可能与您flush()上遗失的writer有关。根据您使用的Writer类型,首先将字节写入需要刷新到流的缓冲区。这可以解释为什么输出中缺少Content-LengthContent-Type。在将其他数据写入流之前,只需将其刷新即可。

进一步致电sendFile("/404.html", sock);。您没有在此处发布完整方法 - 但我认为您在sendFile内递归调用它,从而为您的文件200 OK发送/404.html状态。

答案 2 :(得分:0)

根据您报告的症状,我认为真正的问题是您根本没有与您的服务器交谈!证据是1)您无法获得404响应,2)200响应没有内容长度和类型。如果您真的在谈论上面列出的代码,那么这些都不可能......

也许:

  • 您正在使用旧版本的代码;即在构建/部署周期中出现问题,
  • 您(错误地)尝试在Web容器(Jetty,Tomcat等)中部署/运行代码,或者
  • 您的客户端代码/浏览器实际上是由于代理,不正确的URL或类似内容而与其他服务器通信。

我建议您在代码的适当位置添加一些跟踪打印/日志记录,以确认它实际上已被调用。