import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.Iterator;
import java.net.*;
public class NonblockingSingleFileHTTPServer {
private ByteBuffer contentBuffer;
private int port = 80;
public NonblockingSingleFileHTTPServer(
ByteBuffer data, String encoding, String MIMEType, int port)
throws UnsupportedEncodingException {
this.port = port;
String header = "HTTP/1.0 200 OK\r\n"
+ "Server: OneFile 2.0\r\n"
+ "Content-length: " + data.limit() + "\r\n"
+ "Content-type: " + MIMEType + "\r\n\r\n";
byte[] headerData = header.getBytes("ASCII");
ByteBuffer buffer = ByteBuffer.allocate(
data.limit() + headerData.length);
buffer.put(headerData);
buffer.put(data);
buffer.flip();
this.contentBuffer = buffer;
}
public void run() throws IOException {
ServerSocketChannel serverChannel = ServerSocketChannel.open();
ServerSocket serverSocket = serverChannel.socket();
Selector selector = Selector.open();
InetSocketAddress localPort = new InetSocketAddress(port);
serverSocket.bind(localPort);
serverChannel.configureBlocking(false);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel channel = server.accept();
channel.configureBlocking(false);
SelectionKey newKey = channel.register(selector, SelectionKey.OP_READ);
}
else if (key.isWritable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = (ByteBuffer) key.attachment();
if (buffer.hasRemaining()) {
channel.write(buffer);
}
else { // we're done
channel.close();
}
}
else if (key.isReadable()) {
// Don't bother trying to parse the HTTP header.
// Just read something.
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(4096);
channel.read(buffer);
// switch channel to write-only mode
key.interestOps(SelectionKey.OP_WRITE);
key.attach(contentBuffer.duplicate());
}
}
catch (IOException ex) {
key.cancel();
try {
key.channel().close();
}
catch (IOException cex) {}
}
}
}
}
public static void main(String[] args) {
if (args.length == 0) {
System.out.println(
"Usage: java NonblockingSingleFileHTTPServer file port encoding");
return;
}
try {
String contentType = "text/plain";
if (args[0].endsWith(".html") || args[0].endsWith(".htm")) {
contentType = "text/html";
}
FileInputStream fin = new FileInputStream(args[0]);
FileChannel in = fin.getChannel();
ByteBuffer input = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
// set the port to listen on
int port;
try {
port = Integer.parseInt(args[1]);
if (port < 1 || port > 65535) port = 80;
}
catch (Exception ex) {
port = 80;
}
String encoding = "ASCII";
if (args.length > 2) encoding = args[2];
NonblockingSingleFileHTTPServer server
= new NonblockingSingleFileHTTPServer(
input, encoding, contentType, port);
server.run();
}
catch (Exception ex) {
ex.printStackTrace();
System.err.println(ex);
}
}
}
|