使用java的小型http服务器?

发布于 2024-10-11 08:46:59 字数 3277 浏览 3 评论 0 原文

我使用 java 创建了以下测试服务器:

   import java.io.*;
import java.net.*;

class tcpServer{
    public static void main(String args[]){
        ServerSocket s = null;
        try{
            s = new ServerSocket(7896);
            //right now the stream is open.
            while(true){
                Socket clientSocket = s.accept();
                Connection c = new Connection(clientSocket);
                //now the connection is established
            }
        }catch(IOException e){
            System.out.println("Unable to read: " + e.getMessage());
        }
    }
}
class Connection extends Thread{
    Socket clientSocket;
    BufferedReader din;
    OutputStreamWriter outWriter;

    public Connection(Socket clientSocket){
        try{
            this.clientSocket = clientSocket;
            din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "ASCII"));
            outWriter = new OutputStreamWriter(clientSocket.getOutputStream());
            this.start();
        }catch(IOException e){
            System.out.println("Connection: " + e.getMessage());
        }   
    }
    public void run(){
        try{
        String line = null;
        while((line = din.readLine())!=null){
            System.out.println("Read" + line);
            if(line.length()==0)    
                break;
        }
        //here write the content type etc details:
        System.out.println("Someone connected: " + clientSocket);
        outWriter.write("HTTP/1.1 200 OK\r\n");
        outWriter.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");
        outWriter.write("Expires: -1\r\n");
        outWriter.write("Cache-Control: private, max-age=0\r\n");
        outWriter.write("Content-type: text/html\r\n");
        outWriter.write("Server: vinit\r\n");
        outWriter.write("X-XSS-Protection: 1; mode=block\r\n");
        outWriter.write("<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n");
        }catch(EOFException e){
            System.out.println("EOF: " + e.getMessage());
        }
        catch(IOException e){
            System.out.println("IO at run: " + e.getMessage());
        }finally{
            try{
                            outWriter.close();  
                clientSocket.close();
            }catch(IOException e){
                System.out.println("Unable to close the socket");
            }
        }
    }
}

现在我希望该服务器响应我的浏览器。这就是为什么我给出了 url:http://localhost:7896 结果我在服务器端收到:

ReadGET / HTTP/1.1
ReadHost: localhost:7896
ReadConnection: keep-alive
ReadCache-Control: max-age=0
ReadAccept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
ReadUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10
ReadAccept-Encoding: gzip,deflate,sdch
ReadAccept-Language: en-US,en;q=0.8
ReadAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
ReadCookie: test_cookie=test cookie
Read
Someone connected: Socket[addr=/0:0:0:0:0:0:0:1,port=36651,localport=7896]

并且我的浏览器上出现空白的白屏,源代码也是空白的。在谷歌浏览器中。

那么谁能告诉我哪里错了。实际上我对这件事很陌生。所以请纠正我。

提前致谢

I have created the following test server using java:

   import java.io.*;
import java.net.*;

class tcpServer{
    public static void main(String args[]){
        ServerSocket s = null;
        try{
            s = new ServerSocket(7896);
            //right now the stream is open.
            while(true){
                Socket clientSocket = s.accept();
                Connection c = new Connection(clientSocket);
                //now the connection is established
            }
        }catch(IOException e){
            System.out.println("Unable to read: " + e.getMessage());
        }
    }
}
class Connection extends Thread{
    Socket clientSocket;
    BufferedReader din;
    OutputStreamWriter outWriter;

    public Connection(Socket clientSocket){
        try{
            this.clientSocket = clientSocket;
            din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "ASCII"));
            outWriter = new OutputStreamWriter(clientSocket.getOutputStream());
            this.start();
        }catch(IOException e){
            System.out.println("Connection: " + e.getMessage());
        }   
    }
    public void run(){
        try{
        String line = null;
        while((line = din.readLine())!=null){
            System.out.println("Read" + line);
            if(line.length()==0)    
                break;
        }
        //here write the content type etc details:
        System.out.println("Someone connected: " + clientSocket);
        outWriter.write("HTTP/1.1 200 OK\r\n");
        outWriter.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");
        outWriter.write("Expires: -1\r\n");
        outWriter.write("Cache-Control: private, max-age=0\r\n");
        outWriter.write("Content-type: text/html\r\n");
        outWriter.write("Server: vinit\r\n");
        outWriter.write("X-XSS-Protection: 1; mode=block\r\n");
        outWriter.write("<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n");
        }catch(EOFException e){
            System.out.println("EOF: " + e.getMessage());
        }
        catch(IOException e){
            System.out.println("IO at run: " + e.getMessage());
        }finally{
            try{
                            outWriter.close();  
                clientSocket.close();
            }catch(IOException e){
                System.out.println("Unable to close the socket");
            }
        }
    }
}

Now i want this server to respond to my browser. that's why i gave url: http://localhost:7896
and as a result i receive at the server side:

ReadGET / HTTP/1.1
ReadHost: localhost:7896
ReadConnection: keep-alive
ReadCache-Control: max-age=0
ReadAccept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
ReadUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10
ReadAccept-Encoding: gzip,deflate,sdch
ReadAccept-Language: en-US,en;q=0.8
ReadAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
ReadCookie: test_cookie=test cookie
Read
Someone connected: Socket[addr=/0:0:0:0:0:0:0:1,port=36651,localport=7896]

And a blank white screen at my browser and source code also blank. In google chrome browser.

So can anyone please tell me where i m wrong. actually i am new to this thing. so please correct me.

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

单调的奢华 2024-10-18 08:46:59

您几乎肯定不想在响应上使用 DataOutputStream - 并且 writeUTF 肯定不会做您想要的事情。 DataOutputStream 基本上是为二进制协议设计的 - 并且 writeUTF 写入一个长度前缀的 UTF-8 字符串,而 HTTP 只需要以 CRLF 结尾的 ASCII 文本行。

您想一次写出一行 - 因此在套接字输出流周围创建一个OutputStreamWriter,然后写入:

writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");

等等。

您可能想编写自己的writeLine 方法写出一行,在末尾包含 CRLF(不要使用系统默认的行终止符),使代码更简洁。

在标题和正文之间添加一个空行,然后您应该处于合理的形状。

编辑:还有两个更改:

首先,您应该阅读客户端的请求。例如,将 din 更改为 BufferedReader,并像这样初始化它:

din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),
                                               "ASCII"));

然后在开始写入输出之前,像这样读取请求:

String line;
while ((line = din.readLine()) != null) {
    System.out.println("Read " + line);
    if (line.length() == 0) {
        break;
    }
}

编辑:如注释中所述,这不适用于完整的 HTTP 服务器,因为它不能很好地处理二进制 PUT/POST 数据(它可能会将数据读入其缓冲区,这意味着您无法将其作为二进制数据从流中读取) 。不过对于测试应用程序来说这很好。

最后,您还应该关闭输出写入器或至少刷新它 - 否则它可能会缓冲数据。

进行这些更改后,您的代码对我有用。

You almost certainly don't want to be using DataOutputStream on the response - and writeUTF certainly isn't going to do what you want. DataOutputStream is designed for binary protocols, basically - and writeUTF writes a length-prefixed UTF-8 string, whereas HTTP just wants CRLF-terminated lines of ASCII text.

You want to write headers out a line at a time - so create an OutputStreamWriter around the socket output stream, and write to that:

writer.write("HTTP/1.1 200 OK\r\n");
writer.write("Date: Tue, 11 Jan 2011 13:09:20 GMT\r\n");

etc.

You may want to write your own writeLine method to write out a line including the CRLF at the end (don't use the system default line terminator), to make the code cleaner.

Add a blank line between the headers and the body as well, and then you should be in reasonable shape.

EDIT: Two more changes:

Firstly, you should read the request from the client. For example, change din to a BufferedReader, and initialize it like this:

din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),
                                               "ASCII"));

then before you start to write the output, read the request like this:

String line;
while ((line = din.readLine()) != null) {
    System.out.println("Read " + line);
    if (line.length() == 0) {
        break;
    }
}

EDIT: As noted in comments, this wouldn't be appropriate for a full HTTP server, as it wouldn't handle binary PUT/POST data well (it may read the data into its buffer, meaning you couldn't then read it as binary data from the stream). It's fine for the test app though.

Finally, you should also either close the output writer or at least flush it - otherwise it may be buffering the data.

After making those changes, your code worked for me.

山有枢 2024-10-18 08:46:59

如果您有兴趣学习网络服务器(例如 Java 中的 HTTP 服务器)的设计和开发,您也可以查看此存储库:

https://github.com/berb/java-web-server

这是一个小型的 Java HTTP 服务器,我出于教育目的而开始使用。不过,它还不应该用于生产或严重的用例。我仍在添加新功能。它目前提供多线程、静态文件处理、基本身份验证、日志记录和内存缓存。

编辑

代码中的一个明显错误是响应标头和 HTML 之间缺少 \r\n。只需在最后一个标头中附加一个额外的 \r\n 即可。此外,除非您使用分块编码,否则您必须提供内容长度:

String out = "<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n";

outWriter.write("Content-Length: "+out.getBytes().length+"\r\n\r\n");
outWriter.write(out);

If you're interested in learning the design and development of network servers like HTTP servers in Java, you might also have a look at this repo:

https://github.com/berb/java-web-server

It's a small HTTP server in Java I started for educational purposes. Though, it shouldn't be used in production or serious use cases yet. I'm still adding new features. It currently provides multi-threading, static file handling, Basic Authentication, logging and a in-memory cache.

EDIT

An obvious error in your code is the missing \r\n between your Response Header and your HTML. Just append an additional \r\n to your last header. Additionally, you must provide the content length, unless you're using Chuncked Encoding:

String out = "<html><head><title>Hello</title></head><body>Hello world from my server</body></html>\r\n";

outWriter.write("Content-Length: "+out.getBytes().length+"\r\n\r\n");
outWriter.write(out);
终止放荡 2024-10-18 08:46:59
  • HTTP 协议是基于 ASCII 的,除了主体取决于 Content-Type 标头。所以,没有 UTF-8 标头!
  • 标题和正文必须用空行分隔。
  • 为什么将 Transfert-Encoding 设置为 chunked?你的身体不是。
  • The HTTP protocol is ASCII based, exept the body which depends on the Content-Type header. So, no UTF-8 headers!
  • Headers and body must be separated by an empty line.
  • Why do you set your Transfert-Encoding to chuncked? Your body is not.
盗琴音 2024-10-18 08:46:59

看看这个,它已经为您完成了:

http://www.mcwalter .org/technology/java/httpd/tiny/index.html

Check this out, it's already done for you:

http://www.mcwalter.org/technology/java/httpd/tiny/index.html

美胚控场 2024-10-18 08:46:59

我不确定您是否可以使用 writeUTF 来代替,您可能需要使用 writeBytes 。此外,您需要使用 '\n' 终止每一行。

I'm not sure if you have can use writeUTF instead, instead you may need to use writeBytes. Also, you need to terminate each line with a '\n'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文