对网络中的各种协议认识不足,所以学习下。在学习tomcat服务器的过程中,了解到它是基于一个简单的web服务器慢慢拓展到一个应用广泛的服务器的。
所以,这里做个简单的web服务器
- 创建一个简单的webserver类
package com.chl.webserver;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 一个简单的web服务器( Tomcat )
* @author chenhailong
*
*/
public class WebServer {
/**
* 可以存放一些测试应用程序的静态资源或servlet.是工作目录
*/
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot";
//服务停止命令
public static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
//控制服务状态
private boolean shutdown = false;
public static void main(String[] args) {
WebServer ws = new WebServer();
ws.await();
}
//socket服务端一直接收消息
public void await() {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
}catch(IOException e) {
e.printStackTrace();
System.exit(1);
}
//循环等待请求
while(!shutdown) {
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
//接收到请求之后,await方法从accept方法返回的socket实例中获取input、output对象
socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();
//创建一个Request对象并且调用parse方法解析HTTP请求的原始数据
Request request = new Request(input);
request.parse();
//创建一个Response响应对象
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
//关闭socket
socket.close();
// 判断http请求的uri是不是一个shutdown命令。如果是,则shutdown会置为true,从而推出循环
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}catch(Exception e) {
e.printStackTrace();
continue;
}
}
}
}
- 创建一个简单的request请求类
package com.chl.webserver;
import java.io.IOException;
import java.io.InputStream;
public class Request {
// 输入流
private InputStream input;
// 地址
private String uri;
public Request(InputStream input) {
this.input = input;
}
public String getUri() {
return uri;
}
//解析http请求中的原始数据。
void parse() {
//Read a set of characters from the socket
StringBuffer request = new StringBuffer(2048);
int i ;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
}catch(IOException e) {
e.printStackTrace();
i = -1;
}
for(int j = 0; j< i;j++) {
request.append((char)buffer[j]);
}
System.out.println(request.toString());
uri = parseUri(request.toString());
}
//从 url中返回uri
private String parseUri(String requestString) {
int index1 , index2;
index1 = requestString.indexOf(" ");
if(index1 != -1) {
index2 = requestString.indexOf(" ", index1 + 1);
if(index2 > index1) {
return requestString.substring(index1+1, index2);
}
}
return null;
}
}
3.创建一个response响应类
package com.chl.webserver;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output;
//构造函数创建output对象
public Response(OutputStream output) {
this.output = output;
}
//传递request对象给reponse
public void setRequest(Request request) {
this.request = request;
}
// 输出一个静态资源
public void sendStaticResource() throws IOException{
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
try {
File file = new File(WebServer.WEB_ROOT,request.getUri());
if(file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes,0,BUFFER_SIZE);
while( ch != -1) {
output.write(bytes,0,BUFFER_SIZE);
ch = fis.read(bytes,0,BUFFER_SIZE);
}
}else { //如果不存在,则发送一个异常信息
String errorMessage = "HTTP/1.1 404 File Not Found \r\n"+
"Content-Type : text/html\r\n"+
"Content-Length:23\r\n"+
"\r\n"+
"<h1>File Not Found</h1>";
System.out.println(errorMessage);
output.write(errorMessage.getBytes());
}
}catch(Exception e) {
System.out.println(e.toString());
}finally {
if(fis != null)
fis.close();
}
}
}
- 测试输入 http://127.0.0.1:8080/123
可以看到控制台输出以下信息
## 请求信息
GET /123 HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
## 响应信息
HTTP/1.1 404 File Not Found
Content-Type : text/html
Content-Length:23
<h1>File Not Found</h1>
5.关闭服务 输入http://127.0.0.1:8080/SHUTDOWN
你查看后台,就发现服务已经关闭了。
注:这是一个简单的例子,由繁入简容易,由简入繁可是需要很多的尝试及验证才能证明它的能力。所以还是很佩服这些能写服务器、各种如dubbo协议、hession制定人,能力很强且创造力满满。我们这些造轮子的就明显相形见绌。