import java.io.*; import java.nio.*; import java.nio.channels.*; import java.util.Iterator; import java.net.*; public class asyncHTTPServer { private ByteBuffer contentBuffer; private int port = 80; public asyncHTTPServer( ByteBuffer data, String encoding, String MIMEType, int port) throws UnsupportedEncodingException { this.port = port; // create header 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"; // encode the header using ASCII byte[] headerData = header.getBytes("ASCII"); ByteBuffer buffer = ByteBuffer.allocate(data.limit() + headerData.length); // add content to buffer buffer.put(headerData); buffer.put(data); // reset buffer to the begining buffer.flip(); this.contentBuffer = buffer; } // end of asyncHTTPServer // The main loop public void process_requests() throws IOException { // create selector to monitor events Selector selector = Selector.open(); // create server channel ServerSocketChannel serverChannel = ServerSocketChannel.open(); // bind the port number of the server socket ServerSocket serverSocket = serverChannel.socket(); InetSocketAddress localPort = new InetSocketAddress(port); serverSocket.bind(localPort); serverChannel.configureBlocking(false); // set non-blocking i/o // register the accept event of the server channel to monitor serverChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); // check for available events Iterator keys = selector.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = (SelectionKey) keys.next(); keys.remove(); // remove first event try { if (key.isAcceptable()) { // a new connection is ready to be accepted ServerSocketChannel server = (ServerSocketChannel) key.channel(); // create a new socket channel from the accepted connection SocketChannel channel = server.accept(); // make the new connection nonblocking channel.configureBlocking(false); // register the new connection with READ event SelectionKey newKey = channel.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { // Don't bother trying to parse the HTTP header since we process just one file // 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); // attach the buffer storing the file to be returned key.attach(contentBuffer.duplicate()); } // end of if (key.isReadable()) { 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(); } } // end of else if (key.isWritable()) { } // end of try catch (IOException ex) { key.cancel(); try { key.channel().close(); } catch (IOException cex) {} } //end of catch } // end of while (keys.hasNext()) { } // end of while (true) } // end of run() // main function public static void main(String[] args) { if (args.length == 0) { System.out.println( "Usage: java asyncHTTPServer file port encoding"); return; } try { String contentType = "text/plain"; if (args[0].endsWith(".html") || args[0].endsWith(".htm")) { contentType = "text/html"; } // map the file to a byte buffer 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]; asyncHTTPServer server = new asyncHTTPServer( input, encoding, contentType, port); server.process_requests(); } // end of try catch (Exception ex) { ex.printStackTrace(); System.err.println(ex); } // end of catch } // end of main() } // end of class