import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
public class M4 {
private static Logger log = Logger.getLogger(M4.class.getName());
private static int port = 8080;
private static int readBufSize = 512;
private static Selector selector;
public static void main(String[] args) {
try{
ServerSocketChannel channel = ServerSocketChannel.open();
channel.socket().bind(new InetSocketAddress(port));
channel.configureBlocking(false);
selector = Selector.open();
channel.register(selector, SelectionKey.OP_ACCEPT);
}catch(IOException ex) {
log.log(Level.SEVERE,ex.getMessage(),ex);
return;
}
while(true){
try {
if(selector.select() == 0) {
continue;
}
} catch (Exception e) {
log.log(Level.SEVERE,e.getMessage(),e);
continue;
}
for(Iterator<SelectionKey> iter = selector.selectedKeys().iterator();iter.hasNext();) {
SelectionKey key = iter.next();
iter.remove();
if(key.isAcceptable()) {
connect(key);
} else if (key.isReadable()) {
read(key);
} else if (key.isWritable()) {
writer(key);
}
}
}
}
private static void writer(SelectionKey key) {
Session session = (Session)key.attachment();
try {
if(session.writer() <= 0) {
key.cancel();
key.channel().close();
}
} catch (IOException e) {
session.close();
log.log(Level.INFO,e.getMessage(),e);
}
}
private static void read(SelectionKey key) {
Session session = (Session)key.attachment();
try {
if(session.read() <= 0 ){
key.interestOps(SelectionKey.OP_WRITE);
}else {
if(session.isHeadEnd()) {
key.interestOps(SelectionKey.OP_WRITE);
}
}
} catch (IOException e) {
session.close();
key.cancel();
log.log(Level.INFO,e.getMessage(),e);
}
}
private static void connect(SelectionKey key) {
ServerSocketChannel channel = (ServerSocketChannel)key.channel();
try {
SocketChannel client = channel.accept();
client.configureBlocking(false);
SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
clientKey.attach(new Session(client,readBufSize));
} catch (IOException e) {
log.log(Level.INFO,e.getMessage(),e);
}
}
}
class Session {
private Logger log = Logger.getLogger(this.getClass().getName());
private static final ByteBuffer successHead = ByteBuffer.wrap("HTTP/1.1 200 OK \r\nServer: Simple Server/1.0\r\n\r\n".getBytes());
private static final ByteBuffer notFindHead = ByteBuffer.wrap("HTTP/1.1 404 file not find\r\nServer: Simple Server/1.0\r\n\r\n".getBytes());
private static String basePath;
static{
if(File.separatorChar == '/') {
basePath = "/media/E/openSource/apache/commons/commons-io-2.1/docs";
}else {
basePath = "E:/openSource/apache/commons/commons-io-2.1/docs";
}
}
private SocketChannel client;
private ByteBuffer readBuf;
private boolean headEnd = false;
private StringBuilder builder = new StringBuilder();
private char[] endCheck = new char[4];
private FileChannel outChannel;
private ByteBuffer head;
Session(SocketChannel client,int readBufSize){
this.client = client;
readBuf = ByteBuffer.allocate(readBufSize);
}
public int read() throws IOException {
int count = client.read(readBuf);
if(count > 0) {
readBuf.flip();
if(readBuf.hasRemaining()){
byte[] buf = new byte[readBuf.limit()];
readBuf.get(buf);
builder.append(new String(buf));
int a = buf.length - 4;
if(a >=0 ){
if(buf[a++] == '\r' && buf[a++] =='\n' && buf[a++] == '\r' && buf[a++] == '\n') {
headEnd();
}
}else if(!headEnd && builder.length() >= 4) {
builder.getChars(builder.length()-4, builder.length(), endCheck, 0);
if(endCheck[0] == '\r' && endCheck[1] =='\n' && endCheck[2] == '\r' && endCheck[3] == '\n') {
headEnd();
}
}
}
readBuf.clear();
}
return count;
}
public int writer() throws IOException {
if(null == head){
return -1;
}
if(head.hasRemaining()) {
return client.write(head);
}
if(null != outChannel) {
readBuf.clear();
if(outChannel.read(readBuf) > 0) {
readBuf.flip();
return client.write(readBuf);
}else {
close();
return -1;
}
}
return -1;
}
private void headEnd() {
System.out.println(builder.toString());
headEnd = true;
BufferedReader br = null;
try {
br = new BufferedReader(new StringReader(builder.toString()));
String line = br.readLine();
String[] strs = line.split(" ");
String path = null;
if(strs.length > 1) {
path = strs[1];
}
File file = null;
if(path.equals("\\") || path.equals("/")) {
file = new File(basePath+"/index.html");
}else {
file = new File(basePath+path);
}
if(file.exists()) {
head = successHead.duplicate();
outChannel = new FileInputStream(file).getChannel();
}else {
head = notFindHead.duplicate();
}
} catch (IOException e) {
log.log(Level.SEVERE,e.getMessage(),e);
}finally{
if(null != br) {
try {
br.close();
} catch (IOException e) {
log.log(Level.SEVERE,e.getMessage(),e);
}
}
}
}
public String toHeadString() {
return builder.toString();
}
public boolean isHeadEnd() {
return headEnd;
}
public void close() {
try {
if(client != null && client.isOpen()) {
client.close();
}
} catch (IOException e) {
log.log(Level.SEVERE,e.getMessage(),e);
}finally{
if(null != outChannel && outChannel.isOpen()) {
try {
outChannel.close();
} catch (IOException e) {
log.log(Level.SEVERE,e.getMessage(),e);
}
}
}
}
}
使用nio实现简单的httpServer
最新推荐文章于 2019-10-19 15:22:42 发布