java - 使用java的小型http服务器?

标签 java http sockets network-programming

我已经使用 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]

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

所以任何人都可以告诉我我哪里错了。实际上我对这件事很陌生。所以请纠正我。

提前致谢

最佳答案

您几乎肯定不想在响应中使用 DataOutputStream - 而 writeUTF 肯定不会执行您想要的操作。 DataOutputStream 基本上是为二进制协议(protocol)设计的 - 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 数据(它可能会将数据读入其缓冲区,这意味着你不能那样做从流中将其作为二进制数据读取)。不过,对于测试应用程序来说没问题。

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

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

关于java - 使用java的小型http服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4655355/

相关文章:

java - 将 System.out 返回到字符串

java - 在 Hibernate 中为外键使用 MySQL 索引

java - 严重 : Unable to create initial connections of pool - tomcat 7 with context. xml 文件

r - 如何使用 OpenCPU 通过 HTTP 下载由 rmarkdown 生成的 pdf

c - 如何在Windows 10中正确使用inet_pton rotine?

java - 通过 TCP/IP 的 RS485 通信

java - BufferedReader 链接到套接字,readLine() != null 是如何工作的?

java - 如何处理 UsernameNotFoundException spring security

android - 如何通过 Android 安全地建立以下 HTTPS 连接

security - HTTPS 登录未将 JSESSIONID 保存在 cookie 中