java 编写简易的http服务器
想要写一个http服务器,首先得了解http协议。这里仅介绍一下相关的知识。
1、http协议
HTTP请求报文
在请求中,HTTP报文由方法、URI、HTTP版本、HTTP首部字段等部分构成。其中方法、URI、HTTP版本作为首行,然后每个HTTP首部字段为一行,以上内容简称为请求头,如下请求头:
GET /favicon.ico HTTP/1.1 //首行,GET为请求方法,favicon.ico为url链接,1.1版本号
Host: 172.30.67.185:8080 //以下为首部字段行
Connection: keep-alive
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
注:请求报文一般由浏览器(客户端)向服务器发送
HTTP响应报文
在响应中,HTTP报文由HTTP版本、状态码、HTTP首部字段3部分构成,其中HTTP版本、状态码作为首行,然后每个HTTP首部字段为一行,以上内容简称为响应头,如下响应头:
HTTP/1.1 200 OK //首行,1.1为版本号,200为状态码。以下行为首行字段
Content-Type:text/html;charset=utf-8
//空一行后,响应客户端的内容,后面会讲
注:请求报文一般由服务器向浏览器(客户端)发送
2、简单的http服务器
服务器启动程序
首先,编写一个服务器启动程序,我们监听了8080端口,然后得到socket对象,接着new SocketServer(s),然后启动线程。线程池简单看作启动线程的工具就行了(需要深入了解线程池的自行百度)。
public static void main(String[] args) {
ServerSocket server=null;
//线程池,简单来说,就是把线程start()改成ex.execute(),然后可以提高服务器性能
ExecutorService ex=Executors.newFixedThreadPool(20);
try {
//建立服务器监听端口
server=new ServerSocket(8080);
while(true) {
Socket s=server.accept();
//然后把接收到socket传给SocketServer并执行该线程
ex.execute(new SocketServer(s));
}
} catch (IOException e) {
e.printStackTrace();
}
}
接着,因为我们的SocketServer需要做的是做一个http服务器,所以重点来了!怎么接受浏览器(客户端)传来的请求呢?然后又怎么给浏览器(客户端)响应内容呢?
http服务器类
因为浏览器(客户端)的请求方法有GET、POST等,在这里,先写一个响应GET的请求。
思路:
1、打开socket对象的输入流,接收浏览器(客户端)的请求头
2、分析字段内容,判断请求方法、链接
3、打开socket对象的输出流,在输出流里写入响应头
4、空一行,写入响应内容。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class SocketServer implements Runnable{
Socket s;
//构造方法
public SocketServer(Socket s) {
this.s=s;
}
//线程
public void run(){
//输入输出流
OutputStream os=null;
InputStream in=null;
try
{ //打开socket输入流,并转为BufferedReader流
in=s.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(in));
//接收第一行,得到请求路径
String requestHeader;
requestHeader=br.readLine();
int begin = requestHeader.indexOf("/")+1;
int end = requestHeader.indexOf("HTTP/");
String url="E:\\sublime文件\\Html文件\\第二天案例\\";
url=url+requestHeader.substring(begin, end);
//打开socket对象的输出流,写入响应头
os = s.getOutputStream();
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html;charset=utf-8\r\n".getBytes());
os.write("\r\n".getBytes());
//空一行,写入响应内容。
File f=new File(url);
if(f.exists()) //判断请求的文件是否存在
{
FileInputStream fin=new FileInputStream(f);
byte []b=new byte[1024];
int len;
while((len=fin.read(b))!=-1)
{
os.write(b,0,len);
}
}
os.flush();
//如果os流没有关闭的话,浏览器会以为内容还没传输完成,将一直显示不了内容
os.close();
}
}
实现过程非常简单,简单到没有判断浏览器(客户端)的请求方法,直接返回了一个请求路径的文件。
如有不对之处,直接指正,会做修改