NIO를 이용한 Super Simple 웹서버
1. http://javacan.madvirus.net/ 사이트의 NIO강좌에 있는 웹서버를 참조해서
만들었음.
2. FileChannel.map() 메소드를 이용시 파일복사시에는 700M짜리 파일도
아무 이상없이 복사가 가능함.
3. 그러나 SocketChannel을 이용한 소켓통신에서 FileChannel.map() 메소드를 사용하면 큰용량의 파일(200M 파일로 테스트했음)은 BufferOverFlow 가 발생함. 내 컴터가 문제인지 무엇이 문제인지 모르겠음.
4. 3번문제를 아시는 분은
ward6@naver.com 또는 http://blog.naver.com/ward6 또는 탁재훈 미니홈피에
원인과 해결방법을 올려주면 보은하겠음.
package mySource;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
import java.io.*;
public class SuperSimpleWebServer
{
private Selector selector = null;
private ServerSocketChannel serverSocketChannel = null;
private CharsetDecoder decoder = null;
private ByteBuffer initBuffer = null;
public SuperSimpleWebServer()
{
try
{
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(80));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
decoder = Charset.forName("MS949").newDecoder();
this.initServer();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void initServer()
{
try
{
initBuffer = ByteBuffer.allocateDirect(90);
initBuffer.put("HTTP/1.1 200 OK\n".getBytes());
initBuffer.put("Connection: close\n".getBytes());
initBuffer.put("Server: SimpleWebServer\n".getBytes());
initBuffer.put("Content-Type: text/html\n".getBytes());
initBuffer.put("\n".getBytes());
initBuffer.flip();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void startWebServer()
{
while(true)
{
try
{
selector.select();
Iterator iter = selector.selectedKeys().iterator();
while(iter.hasNext())
{
SelectionKey key = (SelectionKey)iter.next();
if(key.isAcceptable())
{
//accept 처리
this.clientAccept(key);
}
else if(key.isReadable())
{
//read 처리
this.clientRead(key);
}
iter.remove();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
private void clientAccept(SelectionKey key)
{
try
{
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel socketChannel = ssc.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println(socketChannel.socket().getInetAddress() + " 클라이언트가 접속했습니다.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void clientRead(SelectionKey key)
{
ByteBuffer buffer = null;
SocketChannel sc = null;
String fileName = null;
StringTokenizer token = null;
try
{
buffer = ByteBuffer.allocateDirect(1024);
sc = (SocketChannel)key.channel();
sc.read(buffer);
buffer.flip();
token = new StringTokenizer(decoder.decode(buffer).toString(), " ");
token.nextToken();
fileName = token.nextToken();
buffer.clear();
buffer = null;
if(fileName.equals("/"))
{
fileName = "index.html";
}
else
{
fileName = fileName.substring(1);
}
}
catch(Exception e)
{
try
{
sc.close();
}
catch(Exception ex)
{
}
}
this.fileSend(fileName, sc);
}
private void fileSend(String fileName, SocketChannel sc)
{
File file = null;
MappedByteBuffer mbuffer = null;
FileChannel fc = null;
FileInputStream fis = null;
try
{
file = new File(fileName);
fis = new FileInputStream(file);
fc = fis.getChannel();
mbuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0L, fc.size());
sc.write(this.initBuffer);
sc.write(mbuffer);
this.initBuffer.rewind();
}
catch(FileNotFoundException e)
{
// 404 에러
this.errorMessageSend("404", sc);
}
catch(IOException ex)
{
// 500 에러
this.errorMessageSend("500", sc);
}
finally
{
try
{
mbuffer.clear();
mbuffer = null;
fis.close();
fc.close();
sc.close();
}
catch(Exception ex)
{
}
}
}
private void errorMessageSend(String msg, SocketChannel sc)
{
ByteBuffer buffer = null;
try
{
System.out.println(sc.socket().getInetAddress() + " 클라이언트에게 에러 메시지 전송 : " + msg);
buffer = ByteBuffer.allocateDirect(70);
buffer.put("HTTP/1.0 ".getBytes());
buffer.put(msg.getBytes());
buffer.put(" OK\n".getBytes());
buffer.put("Connection: close\n".getBytes());
buffer.put("Server: SimpleWebServer\n".getBytes());
buffer.put("\n".getBytes());
buffer.flip();
sc.write(buffer);
}
catch(Exception e)
{
}
finally
{
try
{
buffer.clear();
buffer = null;
sc.close();
}
catch(Exception ex)
{
}
}
}
public static void main(String[] args)
{
SuperSimpleWebServer webServer = new SuperSimpleWebServer();
webServer.startWebServer();
}
}