Socket、Servlet、Tomcat
一、Socket
? ? ?Socket是網絡編程接口(API),使得開發者可以方便地使用TCP\IP協議進行數據的傳輸,其客戶端與服務端的交互流程為:
二、Http協議
? ? ? ?Web應用程序主要使用HTTP協議,但HTTP協議本身存在兩個問題:無狀態和內容的文本表示。對于前者來說,沒有記錄多個請求之間的關系,而對后者來講,如果使用Java來編程,需要進行文本和Java類型的轉換.
三、Servlet
? ? ?Java針對Web提出了Servlet規范,即提供了Java與HTTP協議溝通的接口,這意味著Java可以以直觀的面向對象的抽象方式編寫HTTP服務端代碼;Servlet接受請求對象,檢查其中的數據,執行適當的后臺邏輯,然后向客戶返回響應。
? ? (1). 提供Java使用HTTP的方法;
? ? (2). 提供了會話機制,解決無狀態問題;
? ? (3). 負責包裝的請求對象,無須開發人員解析傳入的HTTP請求;
四、Tomcat
? ? ? Tomcat是實現Servlet規范的容器,單線程處理簡單示例:
? ? ? Http服務類代碼
public class HttpServer1 {/** WEB_ROOT is the directory where our HTML and other files reside.* For this package, WEB_ROOT is the "webroot" directory under the working* directory.* The working directory is the location in the file system* from where the java command was invoked.*/// shutdown commandprivate static final String SHUTDOWN_COMMAND = "/SHUTDOWN";// the shutdown command receivedprivate boolean shutdown = false;public static void main(String[] args) {HttpServer1 server = new HttpServer1();server.await();}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);}// Loop waiting for a requestwhile (!shutdown) {Socket socket = null;InputStream input = null;OutputStream output = null;try {socket = serverSocket.accept();input = socket.getInputStream();output = socket.getOutputStream();// create Request object and parseRequest request = new Request(input);request.parse();// create Response objectResponse response = new Response(output);response.setRequest(request);// check if this is a request for a servlet or a static resource// a request for a servlet begins with "/servlet/"if (request.getUri().startsWith("/servlet/")) {ServletProcessor1 processor = new ServletProcessor1();processor.process(request, response);}else {StaticResourceProcessor processor = new StaticResourceProcessor();processor.process(request, response);}// Close the socket socket.close();//check if the previous URI is a shutdown commandshutdown = request.getUri().equals(SHUTDOWN_COMMAND);}catch (Exception e) {e.printStackTrace();System.exit(1);}}} }?Servlet處理類代碼:
public class ServletProcessor1 {public void process(Request request, Response response) {String uri = request.getUri();String servletName = uri.substring(uri.lastIndexOf("/") + 1);URLClassLoader loader = null;try {// create a URLClassLoaderURL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(Constants.WEB_ROOT);// the forming of repository is taken from the createClassLoader method in// org.apache.catalina.startup.ClassLoaderFactoryString repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;// the code for forming the URL is taken from the addRepository method in// org.apache.catalina.loader.StandardClassLoader class.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((ServletRequest) request, (ServletResponse) response);}catch (Exception e) {System.out.println(e.toString());}catch (Throwable e) {System.out.println(e.toString());}} }?
多線程:
?
public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();connector.start();} } public class HttpConnector implements Runnable {boolean stopped;private String scheme = "http";public String getScheme() {return scheme;}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() {Thread thread = new Thread(this);thread.start();} }?
public class HttpProcessor {public HttpProcessor(HttpConnector connector) {this.connector = connector;}/*** The HttpConnector with which this processor is associated.*/private HttpConnector connector = null;private HttpRequest request;private HttpRequestLine requestLine = new HttpRequestLine();private HttpResponse response;protected String method = null;protected String queryString = null;/*** The string manager for this package.*/protected StringManager sm =StringManager.getManager("ex03.pyrmont.connector.http");public void process(Socket socket) {SocketInputStream input = null;OutputStream output = null;try {input = new SocketInputStream(socket.getInputStream(), 2048);output = socket.getOutputStream();// create HttpRequest object and parserequest = new HttpRequest(input);// create HttpResponse objectresponse = new HttpResponse(output);response.setRequest(request);response.setHeader("Server", "Pyrmont Servlet Container");parseRequest(input, output);parseHeaders(input);//check if this is a request for a servlet or a static resource//a request for a servlet begins with "/servlet/"if (request.getRequestURI().startsWith("/servlet/")) {ServletProcessor processor = new ServletProcessor();processor.process(request, response);}else {StaticResourceProcessor processor = new StaticResourceProcessor();processor.process(request, response);}// Close the socket socket.close();// no shutdown for this application }catch (Exception e) {e.printStackTrace();}}/*** This method is the simplified version of the similar method in* org.apache.catalina.connector.http.HttpProcessor.* However, this method only parses some "easy" headers, such as* "cookie", "content-length", and "content-type", and ignore other headers.* @param input The input stream connected to our socket** @exception IOException if an input/output error occurs* @exception ServletException if a parsing error occurs*/private void parseHeaders(SocketInputStream input)throws IOException, ServletException {while (true) {HttpHeader header = new HttpHeader();;// Read the next header input.readHeader(header);if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;}else {throw new ServletException(sm.getString("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")) {Cookie cookies[] = RequestUtil.parseCookieHeader(value);for (int i = 0; i < cookies.length; i++) {if (cookies[i].getName().equals("jsessionid")) {// Override anything requested in the URLif (!request.isRequestedSessionIdFromCookie()) {// Accept only the first session id cookie request.setRequestedSessionId(cookies[i].getValue());request.setRequestedSessionCookie(true);request.setRequestedSessionURL(false);}}request.addCookie(cookies[i]);}}else if (name.equals("content-length")) {int n = -1;try {n = Integer.parseInt(value);}catch (Exception e) {throw new ServletException(sm.getString("httpProcessor.parseHeaders.contentLength"));}request.setContentLength(n);}else if (name.equals("content-type")) {request.setContentType(value);}} //end while }private void parseRequest(SocketInputStream input, OutputStream output)throws IOException, ServletException {// Parse the incoming request line 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);}// Checking for an absolute URI (with the HTTP protocol)if (!uri.startsWith("/")) {int pos = uri.indexOf("://");// Parsing out protocol and host nameif (pos != -1) {pos = uri.indexOf('/', pos + 3);if (pos == -1) {uri = "";}else {uri = uri.substring(pos);}}}// Parse any requested session ID out of the request URIString match = ";jsessionid=";int semicolon = uri.indexOf(match);if (semicolon >= 0) {String rest = uri.substring(semicolon + match.length());int semicolon2 = rest.indexOf(';');if (semicolon2 >= 0) {request.setRequestedSessionId(rest.substring(0, semicolon2));rest = rest.substring(semicolon2);}else {request.setRequestedSessionId(rest);rest = "";}request.setRequestedSessionURL(true);uri = uri.substring(0, semicolon) + rest;}else {request.setRequestedSessionId(null);request.setRequestedSessionURL(false);}// Normalize URI (using String operations at the moment)String normalizedUri = normalize(uri);// Set the corresponding request properties ((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 "/", that represents* the canonical version of the specified path after ".." and "." elements* are resolved out. If the specified path attempts to go outside the* boundaries of the current context (i.e. too many ".." path elements* are present), return <code>null</code> instead.** @param path Path to be normalized*/protected String normalize(String path) {if (path == null)return null;// Create a place for the normalized pathString normalized = path;// Normalize "/%7E" and "/%7e" at the beginning to "/~"if (normalized.startsWith("/%7E") || normalized.startsWith("/%7e"))normalized = "/~" + normalized.substring(4);// Prevent encoding '%', '/', '.' and '\', which are special reserved// charactersif ((normalized.indexOf("%25") >= 0)|| (normalized.indexOf("%2F") >= 0)|| (normalized.indexOf("%2E") >= 0)|| (normalized.indexOf("%5C") >= 0)|| (normalized.indexOf("%2f") >= 0)|| (normalized.indexOf("%2e") >= 0)|| (normalized.indexOf("%5c") >= 0)) {return null;}if (normalized.equals("/."))return "/";// Normalize the slashes and add leading slash if necessaryif (normalized.indexOf('\\') >= 0)normalized = normalized.replace('\\', '/');if (!normalized.startsWith("/"))normalized = "/" + normalized;// Resolve occurrences of "//" in the normalized pathwhile (true) {int index = normalized.indexOf("//");if (index < 0)break;normalized = normalized.substring(0, index) +normalized.substring(index + 1);}// Resolve occurrences of "/./" in the normalized pathwhile (true) {int index = normalized.indexOf("/./");if (index < 0)break;normalized = normalized.substring(0, index) +normalized.substring(index + 2);}// Resolve occurrences of "/../" in the normalized pathwhile (true) {int index = normalized.indexOf("/../");if (index < 0)break;if (index == 0)return (null); // Trying to go outside our contextint index2 = normalized.lastIndexOf('/', index - 1);normalized = normalized.substring(0, index2) +normalized.substring(index + 3);}// Declare occurrences of "/..." (three or more dots) to be invalid// (on some Windows platforms this walks the directory tree!!!)if (normalized.indexOf("/...") >= 0)return (null);// Return the normalized path that we have completedreturn (normalized);}}?? ? ? ? 實際上,Tomcat會建立線程池來響應請求,Tomcat的連接數配置可參考:http://www.cnblogs.com/baibaluo/archive/2011/08/23/2150305.html
? ? ? ??
?
轉載于:https://www.cnblogs.com/FrankZhou2017/p/7413516.html
總結
以上是生活随笔為你收集整理的Socket、Servlet、Tomcat的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想杨元庆谈 ChatGPT:坚持用技术
- 下一篇: mstsc.exe是什么(重启的命令是什