使用java的小http服务器?

cod*_*rix 3 java sockets network-programming http

我使用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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我希望这台服务器响应我的浏览器.这就是我给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]
Run Code Online (Sandbox Code Playgroud)

我浏览器和源代码的空白屏幕也是空白.在谷歌浏览器中.

所以任何人都可以告诉我哪里错了.实际上我是这个新手.所以请纠正我.

提前致谢

Jon*_*eet 6

你几乎肯定不想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");
Run Code Online (Sandbox Code Playgroud)

等等

您可能希望编写自己的writeLine方法来写出包括最后CRLF的行(不要使用系统默认行终止符),以使代码更清晰.

在标题和正文之间添加一个空行,然后你应该是合理的形状.

编辑:另外两个变化:

首先,您应该阅读客户端的请求.例如,更改din为a BufferedReader,并将其初始化为:

din = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),
                                               "ASCII"));
Run Code Online (Sandbox Code Playgroud)

然后在开始编写输出之前,请按以下方式读取请求:

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

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

最后,您还应关闭输出编写器或至少刷新它 - 否则它可能正在缓冲数据.

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