Tomcat
主要功能是提供HTTP的服务器。底层使用TCP/IP的进行的socket通信。它遵循了Servlet的规范、进行了具体实现,完成servlet容器的管理。
连接:服务器与客户端进行的Socket通信的连接。
请求:客户端向服务器发送数据。
应答:服务器向客户端发送数据。
HTTP协议:服务器与客户端之间交流的一种协议,通过规定好的结构来识别相互的内容。
BIO(blocking io) 阻塞IO,NIO(non-blocking io) 非阻塞IO,AIO(Asynchronous io) 异步IO
一 HTTP请求协议简介
请求包:
METHOD URL?KEY=VAL VERSION
HEAD_KEY1: HEAD_VAL1
HEAD_KEY2: HEAD_VAL2
BODY
GET /user/userInfos?userIds=123,456,789 HTTP/1.1
Token:ASBJ4KF3SEWDSKNL53H
Host:www.ezone.com
Cookie:XXX=xxx;YYY=yyy
METHOD: 请求的方式例如 GET POST ...
HEAD_KEY: 请求头的名称。
HEAD_VAL: 请求头名称对应的值。
每一行使用\r\n分割。
BODY 请求携带的内容。与请求头之间空出一个空行
应答包:
VERSION STATUS MSG
HEAD_KEY1:HEAD_VAL1
HEAD_KEY2:HEAD_VAL2
BODY
HTTP/1.1 200 OK
Content-Type:application/json;charset=UTF-8
Content-Length:23
{"name":"zzz", state:0}
二 JAVA 使用 TCP实现
JAVA 实现中TCP的通信实现。分别为 BIO NIO NIO2(异步非阻塞 AIO的一种)
1 BIO
服务器
// 服务器
ServerSocket server = new ServerSocket(port, backlog);
// 阻塞并接受客户端的连接、成功返回Socket对象。
Socket client = server.accept();
// 向客户端发送数据的流
OutputStream out = client.getOutputStream();
// 接受客户端当数据的流
InputStream in = client.getInputStream();
客户端
// 客户端创建Socket 与服务器进行连接
Socket client = new Socket(host, port);
// 向服务器发送数据的流
OutputStream out = client.getOutputStream();
// 接受服务器数据的流
InputStream in = client.getInputStream();
2 NIO
服务器
// 开启多路复用选择器
Selector selector = Selector.open();
// 创建server socket 通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// 绑定端口
serverSocketChannel.bind(new InetSocketAddress(8888), 1000);
// NIO模式 为非阻塞、设置为非阻塞,否则无法注册。
serverSocketChannel.configureBlocking(false);
// 注册到Selector上、设置选择事件OP_ACCEPT、当有连接请求接入的时候会触发。
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 3s 轮训的延迟
selector.select(3000);
// 有触发SelectionKey选择的事件将会通过这个方式得到。
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
// 此处进行消费掉!!
iterator.remove();
// 有客户端连接的请求接入
if (selectionKey.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel();
SocketChannel client = server.accept();
// 设置为非阻塞才能注册到 Selector
client.configureBlocking(false);
// 将接入的客户端也注册到多路复用上、有可读数据时会得到这SelectionKey
client.register(selector, SelectionKey.OP_READ);
}
if (selectionKey.isReadable()) {