使用java的小型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");
}
}
}
}
现在我希望该服务器响应我的浏览器。这就是为什么我给出了 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]
并且我的浏览器上出现空白的白屏,源代码也是空白的。在谷歌浏览器中。
那么谁能告诉我哪里错了。实际上我对这件事很陌生。所以请纠正我。
提前致谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您几乎肯定不想在响应上使用
DataOutputStream
- 并且writeUTF
肯定不会做您想要的事情。DataOutputStream
基本上是为二进制协议设计的 - 并且writeUTF
写入一个长度前缀的 UTF-8 字符串,而 HTTP 只需要以 CRLF 结尾的 ASCII 文本行。您想一次写出一行行 - 因此在套接字输出流周围创建一个
OutputStreamWriter
,然后写入:等等。
您可能想编写自己的
writeLine
方法写出一行,在末尾包含 CRLF(不要使用系统默认的行终止符),使代码更简洁。在标题和正文之间添加一个空行,然后您应该处于合理的形状。
编辑:还有两个更改:
首先,您应该阅读客户端的请求。例如,将
din
更改为BufferedReader
,并像这样初始化它:然后在开始写入输出之前,像这样读取请求:
编辑:如注释中所述,这不适用于完整的 HTTP 服务器,因为它不能很好地处理二进制 PUT/POST 数据(它可能会将数据读入其缓冲区,这意味着您无法将其作为二进制数据从流中读取) 。不过对于测试应用程序来说这很好。
最后,您还应该关闭输出写入器或至少刷新它 - 否则它可能会缓冲数据。
进行这些更改后,您的代码对我有用。
You almost certainly don't want to be using
DataOutputStream
on the response - andwriteUTF
certainly isn't going to do what you want.DataOutputStream
is designed for binary protocols, basically - andwriteUTF
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: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 aBufferedReader
, and initialize it like this:then before you start to write the output, read the request like this:
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.
如果您有兴趣学习网络服务器(例如 Java 中的 HTTP 服务器)的设计和开发,您也可以查看此存储库:
https://github.com/berb/java-web-server
这是一个小型的 Java HTTP 服务器,我出于教育目的而开始使用。不过,它还不应该用于生产或严重的用例。我仍在添加新功能。它目前提供多线程、静态文件处理、基本身份验证、日志记录和内存缓存。
编辑
代码中的一个明显错误是响应标头和 HTML 之间缺少 \r\n。只需在最后一个标头中附加一个额外的
\r\n
即可。此外,除非您使用分块编码,否则您必须提供内容长度: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:看看这个,它已经为您完成了:
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
我不确定您是否可以使用 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'
.