Tomcat源码学习一 Tomcat实现基石Socket
来源:互联网 发布:科比 知乎 编辑:程序博客网 时间:2024/05/16 16:11
Tomcat源码学习一 Tomcat实现基石Socket
简述
Tomcat是什么?相信做Java Web的都应该用过Tomcat,它是Web轻量级的应用服务器,或者说是一个Servlet容器。 通过浏览器(Http协议)请求我们的Servlet类配置的路径这个过程是怎样的?Tomcat通过传输层的Socket实现了一个ServerSocket类,等待浏览器的请求并将请求信息封装成Request实例,发送给相应的Servlet,并且将返回结果封装成Response返回给浏览器。HttpServletRequest,HttpServletResponse 两个接口。相信大家都不会陌生,是Http协议的请求和响应。在servlet-api.jar包里这两个接口的实例是怎么来得。这就得在Tomcat源码中寻找答案了。
1.Socket简单实现
Socket又称套接字,是Tcp/Ip传输层的一种应用。下面模拟一个打电话场景.
/** * 电话服务端 * step 1 创建serverSocket * step 2 绑定地址和端口 * step 3 accept 等待客户端连接 * */public class CallServer { public static ServerSocket serverSocket; public static Socket socket; public static BufferedReader reader =null; public static PrintWriter writer = null; public CallServer(String host,int port) { try { // 创建serverSocket serverSocket = new ServerSocket(); // 地址和端口 SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(host),port); // 最大连接数 int backlog = 5; // 绑定地址和端口 serverSocket.bind(endpoint,5); // 阻塞式 等待客户端连接 socket = serverSocket.accept(); System.out.println("Server---------李四 已经连接 接收李四消息!"); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String msg=null; while((msg = reader.readLine())!=null){ System.out.println(msg); } writer = new PrintWriter(socket.getOutputStream()); writer.write("hello lisi"); writer.flush(); writer.close(); reader.close(); socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { CallServer zhangsan = new CallServer("127.0.0.1",8080); }}
/** * 电话客户端 */public class CallClient { private static Socket socket; public static BufferedReader reader =null; public static PrintWriter writer = null; public CallClient(String host,int port) { try { socket = new Socket(); // 地址和端口 SocketAddress endpoint = new InetSocketAddress(InetAddress.getByName(host),port); socket.connect(endpoint); System.out.println("Client---------已经接通张三 接收张三消息!"); writer = new PrintWriter(socket.getOutputStream()); writer.write("hello zhangsan"); writer.flush(); //关闭输出流单项关闭 输出流 不加输出流不关闭,server不会接受到消息 socket.shutdownOutput(); //关闭 输出流会直接关闭socket //writer.close(); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String msg=null; while((msg = reader.readLine())!=null){ System.out.println(msg); } writer.close(); reader.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { CallClient lisi = new CallClient("127.0.0.1",8080); }}
注意:1.在客户端或者服务端通过socket.shutdownOutput()都是单向关闭的,即关闭客户端的输出流并不会关闭服务端的输出流,所以是一种单方向的关闭流2.通过socket.shutdownOutput()关闭输出流,但socket仍然是连接状态,连接并未关闭3.如果直接关闭输入或者输出流,即:in.close()或者out.close(),会直接关闭socket
2.Tomcat Socket源码阅读
2.1 AbstractEndpoint.init()
抽象终端类 用来处理底层 socket 链接。它有三个实现类,分别是3中不同的连接方法。NioEndpoint,AprEndpoint,JIoEndpoint 首相看AbstractEndpoint初始化方法。
// Endpoint 初始化 public final void init() throws Exception { testServerCipherSuitesOrderSupport(); if (bindOnInit) { //绑定端口 其实现serverSocket的bind bind(); bindState = BindState.BOUND_ON_INIT; } }
2.2 JIoEndpoint.bind()
public void bind() throws Exception { //初始化接收器线程数 if (acceptorThreadCount == 0) { acceptorThreadCount = 1; } // 初始化最大连接数 if (getMaxConnections() == 0) { // User hasn't set a value - use the default setMaxConnections(getMaxThreadsInternal()); } if (serverSocketFactory == null) { if (isSSLEnabled()) { //创建ssl serverSocketFactory serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this); } else { serverSocketFactory = new DefaultServerSocketFactory(this); } } if (serverSocket == null) { try { if (getAddress() == null) { //创建 serverSocket serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog()); } else { serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress()); } } catch (BindException orig) { String msg; if (getAddress() == null) msg = orig.getMessage() + " <null>:" + getPort(); else msg = orig.getMessage() + " " + getAddress().toString() + ":" + getPort(); BindException be = new BindException(msg); be.initCause(orig); throw be; } } }
2.3 Acceptor 接收器类
protected class Acceptor extends AbstractEndpoint.Acceptor { @Override public void run() { int errorDelay = 0; // 循环,直到接收到关闭命令为止 while (running) { // 如果端点暂停,则循环 while (paused && running) { state = AcceptorState.PAUSED; try { Thread.sleep(50); } catch (InterruptedException e) { } } if (!running) { break; } state = AcceptorState.RUNNING; try { ////当前连接数 countUpOrAwaitConnection(); Socket socket = null; try { // 此处用来接收 请求 监听客户端连接 // /取出队列中的连接请求 socket = serverSocketFactory.acceptSocket(serverSocket); } catch (IOException ioe) { countDownConnection(); // 必要时引入延迟 errorDelay = handleExceptionWithDelay(errorDelay); throw ioe; } // 成功接受,重置错误延迟 errorDelay = 0; // Configure the socket if (running && !paused && setSocketOptions(socket)) { // TODO 监听到连接后(即浏览器向服务器发起一次请求) ////处理请求 // Hand this socket off to an appropriate processor if (!processSocket(socket)) { countDownConnection(); // 关闭 socket 链接 closeSocket(socket); } } else { countDownConnection(); closeSocket(socket); } } catch (IOException x) { if (running) { log.error(sm.getString("endpoint.accept.fail"), x); } } catch (NullPointerException npe) { if (running) { log.error(sm.getString("endpoint.accept.fail"), npe); } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); log.error(sm.getString("endpoint.accept.fail"), t); } } state = AcceptorState.ENDED; } }
总结
Tomcat实现的基石是Socket,在这里只是简单的分析。也只是冰山一角。其中Socket编程还有很多知识,像Tcp/Ip协议,长连接,短连接等。
阅读全文
0 0
- Tomcat源码学习一 Tomcat实现基石Socket
- tomcat源码学习一
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- Tomcat源码学习(一)
- tomcat学习笔记(一)-导入tomcat源码项目
- 学习tomcat(一)----用IDEA调试tomcat源码
- tomcat源码分析学习笔记(一)
- Tomcat源码分析(一)
- tomcat源码分析[一]
- tomcat源码分析一
- Tomcat源码分析之socket
- Tomcat源码学习(一) 源码编译和导入Eclipse
- jmeter 正则表达式编辑
- PHP中的常用函数
- web的基础知识2
- 欢迎使用CSDN-markdown编辑器
- 同时校验多个String参数是否为空的简单方法
- Tomcat源码学习一 Tomcat实现基石Socket
- 第10周项目1-验证算法
- Kaldi DNN的特征提取和解码的连接操作
- 第12周项目3- Prime算法的验证
- Smart Form中打印图标或符号
- 零售行业数据可视化报告:看看今年双十一怎么玩?
- awk 命令
- Java性能优化指南系列(二):Java 性能分析工具
- Java作业@2017.11.11-11.12