创建一个简单的web服务器
2017-01-04 00:59
447 查看
Web服务器也称为超文本传输协议(HTTP)服务器,因为它使用HTTP来跟客户端进行通信的。既然说到通信那就离不了Java里的两个重要的类java.net.Socket和java.net.ServerSocket。这里浏览器一方可以认为是一个客户端,接收HTTP请求的一方可以认为是服务端。在这之前我们先说一下HTTP协议。
HTTP协议允许web服务器和浏览器通过网络来进行发送和接收数据。它是一种请求和响应协议。客户端发送一个请求,服务端响应这个请求。HTTP请求由三部分组成,分别是:请求行、消息报头(请求头)、请求正文(一般是POST请求)。注意:请求头和请求正文中间有一个空行。一个请求行以一个方法开头,一个空格隔开,后面跟着请求的URI和协议的版本。格式如下Method Request-URI HTTP-Version CRLF。其中Method表示请求方法,Request-URI是一个统一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车和换行(除了作为结尾的CRLF之外,不允许出现单独的CR或LF字符)HTTP响应也是由三个部分组成,分别是:状态行、消息报头(响应头)、响应正文。响应头和响应正文中间有一个空行。状态行的格式如下:HTTP-Version
Status-Code Reason-Phrase CRLF。其中,HTTP-Version表示服务器HTTP协议的版本,Status-Code表示服务器发回的响应状态码,Reason-phrase表示状态代码的文本描述。说了这么多可能你看的还是有点晕,通过下面这张图你应该能看得更清楚一点:
OK,我们上面说了浏览器可以当做是一个客户端,那么我们只需要写一个服务端就行了。下面的代码只是简单的模拟了请求静态资源和处理一个简单的Servlet。
服务端代码如下:
ServletProcessor的代码如下:
package com.zkn.imitate.tomcat.secondchapter.first;
import com.zkn.imitate.tomcat.secondchapter.Request;
import com.zkn.imitate.tomcat.secondchapter.Response;
import com.zkn.imitate.tomcat.utils.Constants;
import com.zkn.imitate.tomcat.utils.StringUtil;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
/**
* Created by wb-zhangkenan on 2016/12/29.
*/
public class ServletProcessor {
/**
* 处理请求信息
* @param request
* @param response
*/
public void process(Request request, Response response){
String str = request.getUri();
String servletName = null;
if(!StringUtil.isEmpty(str) && str.lastIndexOf("/") >= 0){
servletName = str.substring(str.lastIndexOf("/")+1);
}
URLClassLoader classLoader = null;
URL[] url = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
try {
//创建仓库
String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
url[0] = new URL(null,repository,streamHandler);
classLoader = new URLClassLoader(url);//URL类加载器
Class clazz = classLoader.loadClass(servletName);
Servlet servlet = (Servlet) clazz.newInstance();
servlet.service(request,response);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
}
}
下面我们看一下请求结果如何:
当我们输入:http://localhost:8004/FirstServlet时,请求结果如下所示:
当我们输入:http://localhost:8004/static/image01.jpg时,请求结果如下所示:
从上面的结果可以看到,我们做的简单的web服务器可以正常工作了。当然了这个只是最简单的web服务器了,以后我会把这个写的完整一些强大一些。完整的代码请从这里下载:https://github.com/zhangconan/ImitateTomCat
HTTP协议允许web服务器和浏览器通过网络来进行发送和接收数据。它是一种请求和响应协议。客户端发送一个请求,服务端响应这个请求。HTTP请求由三部分组成,分别是:请求行、消息报头(请求头)、请求正文(一般是POST请求)。注意:请求头和请求正文中间有一个空行。一个请求行以一个方法开头,一个空格隔开,后面跟着请求的URI和协议的版本。格式如下Method Request-URI HTTP-Version CRLF。其中Method表示请求方法,Request-URI是一个统一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车和换行(除了作为结尾的CRLF之外,不允许出现单独的CR或LF字符)HTTP响应也是由三个部分组成,分别是:状态行、消息报头(响应头)、响应正文。响应头和响应正文中间有一个空行。状态行的格式如下:HTTP-Version
Status-Code Reason-Phrase CRLF。其中,HTTP-Version表示服务器HTTP协议的版本,Status-Code表示服务器发回的响应状态码,Reason-phrase表示状态代码的文本描述。说了这么多可能你看的还是有点晕,通过下面这张图你应该能看得更清楚一点:
OK,我们上面说了浏览器可以当做是一个客户端,那么我们只需要写一个服务端就行了。下面的代码只是简单的模拟了请求静态资源和处理一个简单的Servlet。
服务端代码如下:
package com.zkn.imitate.tomcat.secondchapter.first; import com.zkn.imitate.tomcat.secondchapter.Request; import com.zkn.imitate.tomcat.secondchapter.Response; import com.zkn.imitate.tomcat.secondchapter.StaticResourceProcessor; import com.zkn.imitate.tomcat.utils.Constants; import com.zkn.imitate.tomcat.utils.StringUtil; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /** * Created by wb-zhangkenan on 2016/12/29. */ public class HttpServer { public static void main(String[] args){ await(); } private static void await() { ServerSocket serverSocket = null; try { boolean shutDown = false; //创建一个服务端 serverSocket = new ServerSocket(8004,1, InetAddress.getByName("127.0.0.1")); while (!shutDown){ //接收客户端请求 Socket socket = serverSocket.accept(); Request request = new Request(socket.getInputStream()); request.parseRequest();//解析请求信息 Response response = new Response(socket.getOutputStream()); String uri = request.getUri(); if(uri !=null && uri.startsWith("/favicon.ico")){ }else if(!StringUtil.isEmpty(uri) && uri.startsWith("/static/")){ StaticResourceProcessor resouce = new StaticResourceProcessor(); resouce.process(request,response);//处理静态资源 }else{ ServletProcessor servletProcessor = new ServletProcessor(); servletProcessor.process(request,response);//处理Servlet } socket.close(); shutDown = Constants.SHUT_DOWN.equals(request.getUri()); } } catch (IOException e) { e.printStackTrace(); } } }模拟的Request主要代码如下:
public class Request implements ServletRequest { /** * 输入流 */ private InputStream inputStream; /** * uri */ private String uri; public Request(InputStream inputStream) { this.inputStream = inputStream; } public void parseRequest(){ BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer sb = new StringBuffer(); String str = null; try { while((str = br.readLine()) != null){ if("".equals(str)) break; sb.append(str).append("\n"); } System.out.println(sb.toString()); uri = StringUtil.parserUri(sb.toString()," "); } catch (IOException e) { e.printStackTrace(); } }模拟的Response主要代码如下:
public class Response implements ServletResponse { /** * 输出流 */ private OutputStream outputStream; /** * 字符输出流 */ private PrintWriter printWriter; public Response(OutputStream outputStream) { this.outputStream = outputStream; } public void sendStaticResource(String path) { FileInputStream fis = null; try { File file = new File(Constants.WEB_PATH, path); if (file.exists() && !file.isDirectory()) { if (file.canRead()) { fis = new FileInputStream(file); int flag = 0; byte[] bytes = new byte[1024]; while ((flag = fis.read(bytes)) != -1){ outputStream.write(bytes); } } }else{ PrintWriter printWriter = getWriter(); //这里用PrintWriter字符输出流,设置自动刷新 printWriter.write("HTTP/1.1 404 File Not Found \r\n"); printWriter.write("Content-Type: text/html\r\n"); printWriter.write("Content-Length: 23\r\n"); printWriter.write("\r\n"); printWriter.write("<h1>File Not Found</h1>"); printWriter.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(fis != null) try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }静态资源处理类:
public class StaticResourceProcessor { public void process(Request request,Response response){ response.sendStaticResource(request.getUri()); } }Servlet处理类如下:
public class FirstServlet implements Servlet{ public void init(ServletConfig servletConfig) throws ServletException { } public ServletConfig getServletConfig() { return null; } public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { PrintWriter out = servletResponse.getWriter(); out.println("Hello. Roses are red."); } public String getServletInfo() { return null; } public void destroy() { } }
ServletProcessor的代码如下:
package com.zkn.imitate.tomcat.secondchapter.first;
import com.zkn.imitate.tomcat.secondchapter.Request;
import com.zkn.imitate.tomcat.secondchapter.Response;
import com.zkn.imitate.tomcat.utils.Constants;
import com.zkn.imitate.tomcat.utils.StringUtil;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
/**
* Created by wb-zhangkenan on 2016/12/29.
*/
public class ServletProcessor {
/**
* 处理请求信息
* @param request
* @param response
*/
public void process(Request request, Response response){
String str = request.getUri();
String servletName = null;
if(!StringUtil.isEmpty(str) && str.lastIndexOf("/") >= 0){
servletName = str.substring(str.lastIndexOf("/")+1);
}
URLClassLoader classLoader = null;
URL[] url = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
try {
//创建仓库
String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
url[0] = new URL(null,repository,streamHandler);
classLoader = new URLClassLoader(url);//URL类加载器
Class clazz = classLoader.loadClass(servletName);
Servlet servlet = (Servlet) clazz.newInstance();
servlet.service(request,response);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
}
}
下面我们看一下请求结果如何:
当我们输入:http://localhost:8004/FirstServlet时,请求结果如下所示:
当我们输入:http://localhost:8004/static/image01.jpg时,请求结果如下所示:
从上面的结果可以看到,我们做的简单的web服务器可以正常工作了。当然了这个只是最简单的web服务器了,以后我会把这个写的完整一些强大一些。完整的代码请从这里下载:https://github.com/zhangconan/ImitateTomCat
相关文章推荐
- 我的Go语言学习之旅八:创建一个简单的WEB服务器
- 找到一个简单构建Web服务器的绿色软件
- [How Tomcat Works]第1章 一个简单的Web服务器
- 通过ASP.NET Web API + JQuery创建一个简单的Web应用
- 使用Restlet创建一个简单的web service(Creating a simple web service with Restlet)
- 基于epoll实现的一个简单web服务器
- java开发的一个简单的本地web服务器
- 使用C# socket 简单构架一个web服务器
- 使用Twisted实现一个简单Web服务器
- 笔试题14:用TCP通信模型创建一个Web服务器(源码)
- 通过ASP.NET Web API + JQuery创建一个简单的Web应用
- 一个简单web服务器的实现
- 用java实现的一个简单web服务器程序
- 一个运行在Web服务器上的远程管理简单例子
- Linux网络管理之四:创建一个简单的vsftpd服务器
- 第18章 一个简单Web服务器的
- WinCE下实现一个简单WEB服务器
- 创建一个yii web应用,是件非常简单的事
- 一个简单的JSPweb工程创建过程
- Tomcat是怎么炼成的?(2)一个最简单的Web服务器