使用java手写一个简单的web服务器(一)
前言: 根据所学的知识进行填充,有些原创有些借鉴,如有错误及侵犯,欢迎指教交流。
我们的第一个Web服务器将是多线程的,所收到的每个Request消息将交由单独的线程进行处理。这使得服务器可以并发地为多个客户服务, 或者是并发地服务于一个客户的多个请求.当创建一个新线程时,需要向线程的构造函数传递实现了Runnable 接口的类的一个实例(即通过实现接口Runnable来实现多线程)。
package com.zhu;
import java.util.*;
import java.io.*;
import java.net.*;
public class WebServer {
//主线程负责监听某个端口,当收到TCP连接请求时,将创建一个新的socket负责与TCP连接
//并创建新的线程负责通过该连接的消息传递
public static void main(String args[]) {
//设置一个端口号,这里可以选择大于1024的任意端口作为web服务器的监听端口,因为小于1024的端口号通常被知名端口占用了
int port = 6789;
//创建监听端口,为了等待TCP连接请求
ServerSocket server = null;
Socket socket = null;
try {
server = new ServerSocket(port);
System.out.println("Web Server is listening on port:" + server.getLocalPort());
//由于web服务器不间断提供服务,所以我们放到一个无穷的循环体中
while (true) {
socket = server.accept();
//启动线程,让HttpRequest在单独的一个线程中处理HTTP请求
new HttpRequest(socket).run();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
//处理Http请求
class HttpRequest implements Runnable {
Socket socket;
//回车换行,根据http规范,回车换行作为Response消息头部行的结束
static String CRLF = "\r\n";
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
//Runnable接口中的run()方法不能抛出异常,所以我们定义processRequest()
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
//流程请求
public void processRequest() throws Exception {
//通过socket的输入流读取消息
InputStream is = socket.getInputStream();
//输出流不需要任何包装,因为我们将向输出流直接写入bytes
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//即从input stream中获得请求行
String requestLine = br.readLine();//读取一行 遇到 回车换行符 结束
System.out.println();
System.out.println(requestLine);
String headerLine = null;
//首部行和实体行之间有一个空行作为分割体
//使用循环读取所有头部行,读取头部行的长度如果为0,表示读出了一个空行
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
//关闭输入输出流以及socket
os.close();
br.close();
socket.close();
//至此,已经完成了Web服务器将显示HTTP Request消息的内容
//可以通过访问 localhost:6789,在java控制台中查看请求报文
}
}