知识点
1.NIO
2.HTTP协议
代码
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
/**
* Created by Administrator on 2017/7/16.
*
* NIO模拟HTTP请求
*/
public class test07HttpServer {
public static void main(String[] args) throws Exception{
//创建ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
//监听端口
ssc.socket().bind(new InetSocketAddress(10010));
//设为非阻塞式
ssc.configureBlocking(false);
//为ssc注册选择器
Selector selector = Selector.open();
ssc.register(selector, SelectionKey.OP_ACCEPT);
//创建处理器
while(true){
//等待请求,每次阻塞三秒,超过三秒后线程继续向下执行,如果传入0或者不传参数一直阻塞
if(selector.select(3000) == 0){
continue;
}
//获取待处理的SelectionKey
Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
while(keyIter.hasNext()){
SelectionKey key = keyIter.next();
//启动新线程处理SelectionKey
new Thread(new HttpHandle(key)).run();
//处理完后,从待处理的SelectionKey迭代器中移除当前所使用的key
keyIter.remove();
}
}
}
private static class HttpHandle implements Runnable{
private final int bufferSize = 1024;//buffer大小
private final String localCharset = "UTF-8";//字符编码
private SelectionKey key;
public HttpHandle(SelectionKey key){
this.key=key;
}
//处理连接请求
public void handleAccept() throws IOException{
SocketChannel clientChannel = ((ServerSocketChannel)key.channel()).accept();
clientChannel.configureBlocking(false);
//注册选择器
clientChannel.register(key.selector(),SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
}
public void handleRead()throws IOException{
//获取channel
SocketChannel sc = (SocketChannel)key.channel();
//获取buffer并重置
ByteBuffer buffer = (ByteBuffer)key.attachment();
buffer.clear();
//没有读到内容则关闭
if(sc.read(buffer) == -1){
sc.close();
}else{
buffer.flip();
String receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
//控制台打印请求报文
String[] requestMessage = receivedString.split("\r\n");
for(String s : requestMessage){
System.out.println(s);
//遇到空行表示报文头已经打印完
if(s.isEmpty())
break;
}
//控制台打印首行信息
String[] firstLine = requestMessage[0].split(" ");
System.out.println();
System.out.println("Method:\t"+firstLine[0]);
System.out.println("url:\t"+firstLine[1]);
System.out.println("HTTP Version:\t"+firstLine[2]);
System.out.println();
//返回客户端
StringBuilder sendString = new StringBuilder();
//响应报文头,200表示成功
sendString.append("HTTP/1.1 200 OK\r\n");
sendString.append("Content-Type:text/html;charset="+localCharset+"\r\n");
sendString.append("\r\n");
sendString.append("<html><head><title>显示报文</title></head><body>");
sendString.append("接受到的请求报文是:<br/>");
for(String s:requestMessage){
sendString.append(s+"<br>");
}
sendString.append("</body></html>");
buffer = ByteBuffer.wrap(sendString.toString().getBytes(localCharset));
sc.write(buffer);
sc.close();
}
}
@Override
public void run() {
try{
//接受到连接请求时
if(key.isAcceptable()){
handleAccept();
}
//读数据
if(key.isReadable()){
handleRead();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
出处《看透Spring MVC 源代码分析与实践》仅作学习笔记