2019独角兽企业重金招聘Python工程师标准>>>

Tomcat中的连接器是一个独立的模块,可以被插入到servlet容器中,而且还有很多连接器可以使用。例如Coyote,mod_jk,mod_jk2,mod_webapp等。Tomcat中使用的连接器必须满足以下条件:

1.实现org.apache.catalina.Connector接口

2.负责创建实现了org.apache.catalina.Request接口的request对象

3.负责创建实现了org.apache.catalina.Response接口的response对象

Tomcat的连接器等待引入的HTTP请求,创建request对象和response对象,然后调用org.apache.catalina.Container接口的invoke()方法,将request对象和response对象传给servlet容器。

package com.whatsmars.tomcat.connector;/*** Created by shenhongxi on 16/4/11.*/
public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();Container container = new SimpleContainer();connector.setContainer(container);connector.setBufferSize(2048);connector.start();}
}
package com.whatsmars.tomcat.connector;import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;/*** Created by shenhongxi on 16/4/11.*/
public class HttpConnector implements Runnable {private Container container;boolean stopped;private String scheme = "http";private int bufferSize;public void run() {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 (!stopped) {// Accept the next incoming connection from the server socketSocket socket = null;try {socket = serverSocket.accept();} catch (Exception e) {continue;}// Hand this socket off to an HttpProcessorHttpProcessor processor = new HttpProcessor(this);processor.process(socket);}}public void start() {new Thread(this).start();}public String getScheme() {return scheme;}public int getBufferSize() {return bufferSize;}public void setBufferSize(int bufferSize) {this.bufferSize = bufferSize;}public Container getContainer() {return container;}public void setContainer(Container container) {this.container = container;}
}
package com.whatsmars.tomcat.connector;import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.ParameterMap;
import org.apache.catalina.util.RequestUtil;import javax.servlet.*;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.*;/*** Created by shenhongxi on 16/4/11.*/
public class HttpRequest implements HttpServletRequest {private String requestURI;private int contentLength;private String contentType;private String queryString;private String method;private String protocol;protected Map headers = new HashMap();protected SocketInputStream input;/*** The parsed parameters for this request.  This is populated only if* parameter information is requested via one of the* <code>getParameter()</code> family of method calls.  The key is the* parameter name, while the value is a String array of values for this* parameter.* <p>* <strong>IMPLEMENTATION NOTE</strong> - Once the parameters for a* particular request are parsed and stored here, they are not modified.* Therefore, application level access to the parameters need not be* synchronized.*/protected ParameterMap parameters = null; // extends LinkedHashMap has a boolean var 'locked'/*** Have the parameters for this request been parsed yet?*/protected boolean parsed = false;public HttpRequest(SocketInputStream input) {this.input = input;}public void addHeader(String name, String value) {name = name.toLowerCase();synchronized (headers) {ArrayList values = (ArrayList) headers.get(name);if (values == null) {values = new ArrayList();headers.put(name, values);}values.add(value);}}public String getParameter(String name) {parseParameters();String values[] = (String[]) parameters.get(name);if (values != null)return (values[0]);elsereturn (null);}public Map getParameterMap() {parseParameters();return (this.parameters);}public Enumeration getParameterNames() {parseParameters();return (new Enumerator(parameters.keySet()));}public String[] getParameterValues(String name) {parseParameters();String values[] = (String[]) parameters.get(name);if (values != null)return (values);elsereturn null;}/*** Parse the parameters of this request, if it has not already occurred.* If parameters are present in both the query string and the request* content, they are merged.*/protected void parseParameters() {if (parsed) return;ParameterMap results = parameters;if (results == null)results = new ParameterMap();results.setLocked(false);String encoding = getCharacterEncoding();if (encoding == null)encoding = "ISO-8859-1";// Parse any parameters specified in the query stringString queryString = getQueryString();try {RequestUtil.parseParameters(results, queryString, encoding);} catch (Exception e) {;}// Parse any parameters specified in the input streamString contentType = getContentType();if (contentType == null)contentType = "";int semicolon = contentType.indexOf(';');if (semicolon >= 0) {contentType = contentType.substring(0, semicolon).trim();} else {contentType = contentType.trim();}if ("POST".equals(getMethod()) && (getContentLength() > 0)&& "application/x-www-form-urlencoded".equals(contentType)) {try {int max = getContentLength();int len = 0;byte buf[] = new byte[getContentLength()];ServletInputStream is = getInputStream();while (len < max) {int next = is.read(buf, len, max - len);if (next < 0 ) {break;}len += next;}is.close();if (len < max) {throw new RuntimeException("Content length mismatch");}RequestUtil.parseParameters(results, buf, encoding);} catch (UnsupportedEncodingException ue) {;} catch (IOException e) {throw new RuntimeException("Content read fail");}}// Store the final resultsresults.setLocked(true);parsed = true;parameters = results;}public void setRequestURI(String requestURI) {this.requestURI = requestURI;}public void setContentLength(int contentLength) {this.contentLength = contentLength;}public void setContentType(String contentType) {this.contentType = contentType;}public void setQueryString(String queryString) {this.queryString = queryString;}public void setMethod(String method) {this.method = method;}public void setProtocol(String protocol) {this.protocol = protocol;}// ... other methods
}
package com.whatsmars.tomcat.connector;import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Locale;/*** Created by shenhongxi on 16/4/11.*/
public class HttpResponse implements HttpServletResponse {OutputStream output;HttpRequest request;PrintWriter writer;public HttpResponse(OutputStream output) {this.output = output;}public void setRequest(HttpRequest request) {this.request = request;}/*** call this method to send headers and response to the output*/public void finishResponse() {// sendHeaders();// Flush and close the appropriate output mechanismif (writer != null) {writer.flush();writer.close();}}public void addCookie(Cookie cookie) {}public boolean containsHeader(String name) {return false;}public String encodeURL(String url) {return null;}public String encodeRedirectURL(String url) {return null;}public String encodeUrl(String url) {return null;}public String encodeRedirectUrl(String url) {return null;}public void sendError(int sc, String msg) throws IOException {}public void sendError(int sc) throws IOException {}public void sendRedirect(String location) throws IOException {}// ... other methods
}
package com.whatsmars.tomcat.connector;import com.whatsmars.tomcat.servlet.StaticResourceProcessor;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;/*** Created by shenhongxi on 16/4/11.*/
public class HttpProcessor {private HttpConnector connector;private HttpRequest request;private HttpResponse response;private HttpRequestLine requestLine = new HttpRequestLine();public HttpProcessor(HttpConnector connector) {this.connector = connector;}public void process(Socket socket) {SocketInputStream input = null;OutputStream output = null;try {input = new SocketInputStream(socket.getInputStream(), connector.getBufferSize()); // 1.读取套接字的输入流output = socket.getOutputStream();// create HttpRequest object and parserequest = new HttpRequest(input);response = new HttpResponse(output);response.setRequest(request);response.setHeader("Server", "Mars Servlet Container");parseRequest(input, output); // 解析请求行,即HTTP请求的第一行内容parseHeaders(input); // 解析请求头if (request.getRequestURI().startsWith("/servlet/")) {connector.getContainer().invoke((HttpServletRequest) request, (HttpServletResponse) response);} else {StaticResourceProcessor processor = new StaticResourceProcessor();//processor.process(request, response);}socket.close();} catch (Exception e) {e.printStackTrace();}}private void parseHeaders(SocketInputStream input) throws IOException, ServletException{while (true) { // 一行一行解析完headerHttpHeader header = new HttpHeader();// Read the next headerinput.readHeader(header);if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;} else {throw new ServletException("httpProcessor parseHeaders colon");}}String name = new String(header.name, 0, header.nameEnd);String value = new String(header.value, 0, header.valueEnd);request.addHeader(name, value);// do something for some headers, ignore others.if (name.equals("cookie")) {// ...// request.addCookie(cookies[i]);} else if (name.equals("content-length")) {int n = -1;try {n = Integer.parseInt(value);} catch (Exception e) {throw new ServletException("httpProcessor.parseHeaders.contentLength");}request.setContentLength(n);} else if (name.equals("content-type")) {request.setContentType(value);}}}private void parseRequest(SocketInputStream input, OutputStream output) throws IOException, ServletException {input.readRequestLine(requestLine);String method = new String(requestLine.method, 0, requestLine.methodEnd);String uri = null;String protocol = new String(requestLine.protocol, 0, requestLine.protocolEnd);// Validate the incoming request lineif (method.length() < 1) {throw new ServletException("Missing HTTP request method");} else if (requestLine.uriEnd < 1) {throw new ServletException("Missing HTTP request URI");}// Parse any query parameters out of the request URIint question = requestLine.indexOf("?");if (question >= 0) {request.setQueryString(new String(requestLine.uri, question + 1,requestLine.uriEnd - question - 1));uri = new String(requestLine.uri, 0, question);} else {request.setQueryString(null);uri = new String(requestLine.uri, 0, requestLine.uriEnd);}String normalizedUri = normalize(uri);((HttpRequest) request).setMethod(method);request.setProtocol(protocol);if (normalizedUri != null) {((HttpRequest) request).setRequestURI(normalizedUri);}else {((HttpRequest) request).setRequestURI(uri);}if (normalizedUri == null) {throw new ServletException("Invalid URI: " + uri + "'");}}// Return a context-relative path, beginning with a "/"protected String normalize(String path) {if (path == null) return null;String normalized = path;// ...return path;}
}
package com.whatsmars.tomcat.connector;/*** Created by shenhongxi on 16/4/13.*/
public final class HttpHeader {public static final int INITIAL_NAME_SIZE = 32;public static final int INITIAL_VALUE_SIZE = 64;public static final int MAX_NAME_SIZE = 128;public static final int MAX_VALUE_SIZE = 4096;public char[] name;public int nameEnd;public char[] value;public int valueEnd;protected int hashCode = 0;public HttpHeader() {this(new char[INITIAL_NAME_SIZE], 0, new char[INITIAL_VALUE_SIZE], 0);}public HttpHeader(char[] name, int nameEnd, char[] value, int valueEnd) {this.name = name;this.nameEnd = nameEnd;this.value = value;this.valueEnd = valueEnd;}public HttpHeader(String name, String value) {this.name = name.toLowerCase().toCharArray();this.nameEnd = name.length();this.value = value.toCharArray();this.valueEnd = value.length();}/*** Release all object references, and initialize instance variables, in* preparation for reuse of this object.*/public void recycle() {nameEnd = 0;valueEnd = 0;hashCode = 0;}}
package com.whatsmars.tomcat.connector;/*** Created by shenhongxi on 16/4/13.*/
public final class HttpRequestLine {public static final int INITIAL_METHOD_SIZE = 8;public static final int INITIAL_URI_SIZE = 64;public static final int INITIAL_PROTOCOL_SIZE = 8;public static final int MAX_METHOD_SIZE = 1024;public static final int MAX_URI_SIZE = 32768;public static final int MAX_PROTOCOL_SIZE = 1024;public char[] method;public int methodEnd;public char[] uri;public int uriEnd;public char[] protocol;public int protocolEnd;public HttpRequestLine() {this(new char[INITIAL_METHOD_SIZE], 0, new char[INITIAL_URI_SIZE], 0,new char[INITIAL_PROTOCOL_SIZE], 0);}public HttpRequestLine(char[] method, int methodEnd,char[] uri, int uriEnd,char[] protocol, int protocolEnd) {this.method = method;this.methodEnd = methodEnd;this.uri = uri;this.uriEnd = uriEnd;this.protocol = protocol;this.protocolEnd = protocolEnd;}public int indexOf(String str) {// ...return -1;}/*** Release all object references, and initialize instance variables, in* preparation for reuse of this object.*/public void recycle() {methodEnd = 0;uriEnd = 0;protocolEnd = 0;}}
package com.whatsmars.tomcat.connector;import java.io.IOException;
import java.io.InputStream;/*** Created by shenhongxi on 16/4/11.* Extends InputStream to be more efficient reading lines during HTTP header processing.*/
public class SocketInputStream extends InputStream {/*** Underlying input stream.*/private InputStream input;/*** Internal buffer.*/protected byte[] buf;/*** Last valid byte.*/protected int count;/*** Position in the buffer.*/protected int pos;public SocketInputStream(InputStream input, int bufferSize) {this.input = input;this.buf = new byte[bufferSize];}// input => buf => HttpRequestLinepublic void readRequestLine(HttpRequestLine requestLine) throws IOException {// Recycling checkif (requestLine.methodEnd != 0)requestLine.recycle();// Checking for a blank line// Reading the method name// Reading URI// Reading protocol}// input => buf => HttpHeaderpublic void readHeader(HttpHeader header) throws IOException {// Recycling checkif (header.nameEnd != 0)header.recycle();// Checking for a blank line// Reading the header name// Reading the header value (which can be spanned over multiple lines)}@Overridepublic int read() throws IOException {if (pos >= count) {fill();if (pos >= count)return -1;}return buf[pos++] & 0xff;}/*** Fill the internal buffer using data from the undelying input stream.*/protected void fill()throws IOException {pos = 0;count = 0;int nRead = input.read(buf, 0, buf.length);if (nRead > 0) {count = nRead;}}
}
package com.whatsmars.tomcat.connector;import com.whatsmars.tomcat.servlet.Constants;import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;/*** Created by shenhongxi on 16/4/14.*/
public class SimpleContainer implements Container {public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {String servletName = ( (HttpServletRequest) request).getRequestURI();servletName = servletName.substring(servletName.lastIndexOf("/") + 1);URLClassLoader loader = null;try {URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(Constants.WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);} catch (IOException e) {System.out.println(e.toString() );}Class myClass = null;try {myClass = loader.loadClass(servletName);}catch (ClassNotFoundException e) {System.out.println(e.toString());}Servlet servlet = null;try {servlet = (Servlet) myClass.newInstance();servlet.service((HttpServletRequest) request, (HttpServletResponse) response);}catch (Exception e) {System.out.println(e.toString());}catch (Throwable e) {System.out.println(e.toString());}}
}
package com.whatsmars.tomcat.connector;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** Created by shenhongxi on 16/4/14.*/
public interface Container {public void invoke(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
}

最后,关于HttpProcessor池,连接器线程和处理器线程的等待与唤醒,请参考多线程知识自行脑补。

Request和Response的外观类(包装类)参见http://wely.iteye.com/blog/2290575

转载于:https://my.oschina.net/javahongxi/blog/1523782

模拟tomcat连接器相关推荐

  1. 谈谈Tomcat连接器

    " Tomcat 作为应用最广泛的 Web 容器被各大厂商所使用,从体系结构上看 Tomcat 分为连接器和容器两个部分.其中连接器负责 IO 请求转换.网络请求解析以及请求适配等工作. 图 ...

  2. Tomcat - 模拟Tomcat的webappClassLoader加载自己war包应用内不同版本类实现相互共存与隔离

    文章目录 Pre Tomcat要解决什么问题? Tomcat违反了双亲委派机制? 模拟Tomcat的webappClassLoader加载自己war包应用内不同版本类实现相互共存与隔离 Tomcat加 ...

  3. [转]Loadrunner Error code 10053 Tomcat 连接器(connector)优化

    LoadRunner提示错误:Error : socket0 - Software caused connection abort. Error code : 10053. 在今天的测试过程中发现,s ...

  4. 利用反射模拟Tomcat类加载器的toString方法

    一直认为tomcat5的类加载器的toString方法很酷,为什么呢?因为它的toString方法列出了所有的父类加载器以及类加载器加载的资源(即classpath).可能有些朋友还没有注意过,如果想 ...

  5. 性能追击:万字长文30+图揭秘8大主流服务器程序线程模型 | Node.js,Apache,Nginx,Netty,Redis,Tomcat,MySQL,Zuul

    本文为<高性能网络编程游记>的第六篇"性能追击:万字长文30+图揭秘8大主流服务器程序线程模型". 最近拍的照片比较少,不知道配什么图好,于是自己画了一个,凑合着用,让 ...

  6. Tomcat 调优及 JVM 参数优化

    Tomcat 本身与 JVM 优化 Tomcat:调整Server.xml JVM:bat启动服务方式的话修改catalina.bat 服务式启动的话参考:http://www.cnblogs.com ...

  7. Tomcat参数配置

    2019独角兽企业重金招聘Python工程师标准>>> 1. JAVA_OPTS内存优化 Tomcat内存优化主要是对启动参数的优化,可以在Tomcat的启动脚本catalina.s ...

  8. (014)java后台开发之用tomcat发布自己的javaWeb项目

    本地模拟tomcat发布javaWeb项目需要: 1.Mac本地安装tomcat. 2.Mac安装Eclipse-JavaEE. 3.tomcat 在Mac的安装. (http://blog.csdn ...

  9. 面试必问!Tomcat 优化篇!

    前言 Tomcat 服务器是一个开源的轻量级Web应用服务器,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet.JSP 程序的首选.相信大家对于 Tomcat 已经是非常熟悉了,本 ...

  10. Tomcat介绍及性能优化

    一.Tomcat简单介绍: Sun公司创建了第一个Servlet容器,即Java Web Server,但JWS只是为了演示Servlet的相应功能,所以其性能很不稳定.与此同时,apache基金会组 ...

最新文章

  1. vue 函数 路由跳转_vue路由的钩子函数和跳转
  2. android 悬浮窗口和主界面同时显示,Android 悬浮窗口(及解决6.0以上无法显示问题)...
  3. 前端面试题之http/HTML/浏览器(一)
  4. 监听vuex的某条数据
  5. skywalking原理_微服务链路追踪原理
  6. 量子计算时代到来,摩尔定律将要失效?
  7. 抓包工具 for Mac之paros
  8. Struts2 result type(结果类型)
  9. 常见浏览器兼容性问题与解决方案(CSS)
  10. java架构专题涨价_关于单量预测和动态定价的一些思考
  11. minst 手写数字识别实战
  12. JDK10安装与配置
  13. PM Interview 60quiz
  14. sue的小球 牛客(区间dp)
  15. 14.JDK底层Unsafe类是个啥东西?
  16. JavaWeb学习笔记之——HTML
  17. 网络游戏外挂分类及实例
  18. 打印机使用技巧:打印机的另类用法
  19. Spark 在YARN上运行
  20. 码工里开关灯为什么遮罩层在下面_拆成零件看看,什么样的开关插座值得买?...

热门文章

  1. php版给UEditor的图片在线管理栏目增加图片删除功能
  2. POJ2031Building a Space Station
  3. hdu 2550 百步穿杨(大水题)
  4. 2011总结与2012展望
  5. [转]CellCtrl控件完美破解研究
  6. 泛化误差,交叉验证和特征选择
  7. 黑苹果OC引导配置制作小工具:一键制作黑苹果OpenCore EFI文件
  8. 通过Wi-Fi将iPhone与Mac同步的教程
  9. javaScript---ES6解构赋值
  10. Spring2.5整合ActiveMQ 5.2(P2P文本消息)