[Assorted-commits] SF.net SVN: assorted:[1474] sandbox/trunk/src/java
Brought to you by:
yangzhang
From: <yan...@us...> - 2009-09-21 06:04:54
|
Revision: 1474 http://assorted.svn.sourceforge.net/assorted/?rev=1474&view=rev Author: yangzhang Date: 2009-09-21 06:04:40 +0000 (Mon, 21 Sep 2009) Log Message: ----------- imported nio server example from sron Modified Paths: -------------- sandbox/trunk/src/java/footprint/go.bash Added Paths: ----------- sandbox/trunk/src/java/MinaUdpExample2.java sandbox/trunk/src/java/nio-server-example/ sandbox/trunk/src/java/nio-server-example/ChangeRequest.java sandbox/trunk/src/java/nio-server-example/EchoWorker.java sandbox/trunk/src/java/nio-server-example/Makefile sandbox/trunk/src/java/nio-server-example/NioServer.java sandbox/trunk/src/java/nio-server-example/README sandbox/trunk/src/java/nio-server-example/ServerDataEvent.java Added: sandbox/trunk/src/java/MinaUdpExample2.java =================================================================== --- sandbox/trunk/src/java/MinaUdpExample2.java (rev 0) +++ sandbox/trunk/src/java/MinaUdpExample2.java 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,52 @@ + + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.mina.common.IoHandlerAdapter; +import org.apache.mina.common.IoSession; +import org.apache.mina.common.ThreadModel; +import org.apache.mina.transport.socket.nio.DatagramAcceptor; +import sun.nio.ch.DatagramSocketAdaptor; + +public class Test { + + public static void main(String[] args) throws Exception { + InetAddress addr = InetAddress.getLocalHost(); + ScheduledExecutorService executor = Executors + .newSingleThreadScheduledExecutor(); + executor.schedule(new Runnable() { + public void run() { + System.out.println("hello world"); + } + }, 10, TimeUnit.MILLISECONDS); + DatagramAcceptor a = new DatagramAcceptor(executor); + a.getDefaultConfig().setThreadModel(ThreadModel.MANUAL); + for (int i = 0; i < 2; i++) { + a.bind(new InetSocketAddress(addr, 10000 + i), + new IoHandlerAdapter() { + public void messageReceived(IoSession session, + Object obj) throws Exception { + System.out.println("received " + obj + " on " + + session.getLocalAddress() + " in thread " + + Thread.currentThread().getName()); + } + }); + } + System.out.println("hello"); + while (true) { + Thread.sleep(1000); + byte[] buf = new byte[2]; + DatagramSocket s = new DatagramSocket(); + s.send(new DatagramPacket(buf, buf.length, addr, 10000)); + s.send(new DatagramPacket(buf, buf.length, addr, 10001)); + } + } +} Modified: sandbox/trunk/src/java/footprint/go.bash =================================================================== --- sandbox/trunk/src/java/footprint/go.bash 2009-09-21 05:39:24 UTC (rev 1473) +++ sandbox/trunk/src/java/footprint/go.bash 2009-09-21 06:04:40 UTC (rev 1474) @@ -1,12 +1,11 @@ #!/usr/bin/env bash javac Main.java -java -server Main & -#java Main & +java Main & pid=$! for i in 1 2; do sleep 1 - ps -o rss= $pid + ps -o vsz= -o rss= $pid done wait @@ -15,8 +14,8 @@ pid=$! for i in 1 2 ; do sleep 1 - ps -o rss= $pid + ps -o vsz= -o rss= $pid done wait -# Results: Java takes ~12.3MB, Mono takes ~5.1MB +# Results: Java takes ~12.3MB RSS/860MN VSZ, Mono takes ~5.1MB RSS/43MB VSZ Added: sandbox/trunk/src/java/nio-server-example/ChangeRequest.java =================================================================== --- sandbox/trunk/src/java/nio-server-example/ChangeRequest.java (rev 0) +++ sandbox/trunk/src/java/nio-server-example/ChangeRequest.java 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,16 @@ +import java.nio.channels.SocketChannel; + +public class ChangeRequest { + public static final int REGISTER = 1; + public static final int CHANGEOPS = 2; + + public SocketChannel socket; + public int type; + public int ops; + + public ChangeRequest(SocketChannel socket, int type, int ops) { + this.socket = socket; + this.type = type; + this.ops = ops; + } +} \ No newline at end of file Added: sandbox/trunk/src/java/nio-server-example/EchoWorker.java =================================================================== --- sandbox/trunk/src/java/nio-server-example/EchoWorker.java (rev 0) +++ sandbox/trunk/src/java/nio-server-example/EchoWorker.java 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,36 @@ +import java.nio.channels.SocketChannel; +import java.util.LinkedList; +import java.util.List; + +public class EchoWorker implements Runnable { + private List queue = new LinkedList(); + + public void processData(NioServer server, SocketChannel socket, byte[] data, int count) { + byte[] dataCopy = new byte[count]; + System.arraycopy(data, 0, dataCopy, 0, count); + synchronized(queue) { + queue.add(new ServerDataEvent(server, socket, dataCopy)); + queue.notify(); + } + } + + public void run() { + ServerDataEvent dataEvent; + + while(true) { + // Wait for data to become available + synchronized(queue) { + while(queue.isEmpty()) { + try { + queue.wait(); + } catch (InterruptedException e) { + } + } + dataEvent = (ServerDataEvent) queue.remove(0); + } + + // Return to sender + dataEvent.server.send(dataEvent.socket, dataEvent.data); + } + } +} \ No newline at end of file Added: sandbox/trunk/src/java/nio-server-example/Makefile =================================================================== --- sandbox/trunk/src/java/nio-server-example/Makefile (rev 0) +++ sandbox/trunk/src/java/nio-server-example/Makefile 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,4 @@ +all: NioServer.class + +NioServer.class: NioServer.java + javac $< Added: sandbox/trunk/src/java/nio-server-example/NioServer.java =================================================================== --- sandbox/trunk/src/java/nio-server-example/NioServer.java (rev 0) +++ sandbox/trunk/src/java/nio-server-example/NioServer.java 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,205 @@ +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +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.channels.spi.SelectorProvider; +import java.util.*; + +public class NioServer implements Runnable { + // The host:port combination to listen on + private InetAddress hostAddress; + private int port; + + // The channel on which we'll accept connections + private ServerSocketChannel serverChannel; + + // The selector we'll be monitoring + private Selector selector; + + // The buffer into which we'll read data when it's available + private ByteBuffer readBuffer = ByteBuffer.allocate(8192); + + private EchoWorker worker; + + // A list of PendingChange instances + private List pendingChanges = new LinkedList(); + + // Maps a SocketChannel to a list of ByteBuffer instances + private Map pendingData = new HashMap(); + + public NioServer(InetAddress hostAddress, int port, EchoWorker worker) throws IOException { + this.hostAddress = hostAddress; + this.port = port; + this.selector = this.initSelector(); + this.worker = worker; + } + + public void send(SocketChannel socket, byte[] data) { + synchronized (this.pendingChanges) { + // Indicate we want the interest ops set changed + this.pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE)); + + // And queue the data we want written + synchronized (this.pendingData) { + List queue = (List) this.pendingData.get(socket); + if (queue == null) { + queue = new ArrayList(); + this.pendingData.put(socket, queue); + } + queue.add(ByteBuffer.wrap(data)); + } + } + + // Finally, wake up our selecting thread so it can make the required changes + this.selector.wakeup(); + } + + public void run() { + while (true) { + try { + // Process any pending changes + synchronized (this.pendingChanges) { + Iterator changes = this.pendingChanges.iterator(); + while (changes.hasNext()) { + ChangeRequest change = (ChangeRequest) changes.next(); + switch (change.type) { + case ChangeRequest.CHANGEOPS: + SelectionKey key = change.socket.keyFor(this.selector); + key.interestOps(change.ops); + } + } + this.pendingChanges.clear(); + } + + // Wait for an event one of the registered channels + this.selector.select(); + + // Iterate over the set of keys for which events are available + Iterator selectedKeys = this.selector.selectedKeys().iterator(); + while (selectedKeys.hasNext()) { + SelectionKey key = (SelectionKey) selectedKeys.next(); + selectedKeys.remove(); + + if (!key.isValid()) { + continue; + } + + // Check what event is available and deal with it + if (key.isAcceptable()) { + this.accept(key); + } else if (key.isReadable()) { + this.read(key); + } else if (key.isWritable()) { + this.write(key); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void accept(SelectionKey key) throws IOException { + // For an accept to be pending the channel must be a server socket channel. + ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); + + // Accept the connection and make it non-blocking + SocketChannel socketChannel = serverSocketChannel.accept(); + Socket socket = socketChannel.socket(); + socketChannel.configureBlocking(false); + + // Register the new SocketChannel with our Selector, indicating + // we'd like to be notified when there's data waiting to be read + socketChannel.register(this.selector, SelectionKey.OP_READ); + } + + private void read(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + + // Clear out our read buffer so it's ready for new data + this.readBuffer.clear(); + + // Attempt to read off the channel + int numRead; + try { + numRead = socketChannel.read(this.readBuffer); + } catch (IOException e) { + // The remote forcibly closed the connection, cancel + // the selection key and close the channel. + key.cancel(); + socketChannel.close(); + return; + } + + if (numRead == -1) { + // Remote entity shut the socket down cleanly. Do the + // same from our end and cancel the channel. + key.channel().close(); + key.cancel(); + return; + } + + // Hand the data off to our worker thread + this.worker.processData(this, socketChannel, this.readBuffer.array(), numRead); + } + + private void write(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + + synchronized (this.pendingData) { + List queue = (List) this.pendingData.get(socketChannel); + + // Write until there's not more data ... + while (!queue.isEmpty()) { + ByteBuffer buf = (ByteBuffer) queue.get(0); + socketChannel.write(buf); + if (buf.remaining() > 0) { + // ... or the socket's buffer fills up + break; + } + queue.remove(0); + } + + if (queue.isEmpty()) { + // We wrote away all data, so we're no longer interested + // in writing on this socket. Switch back to waiting for + // data. + key.interestOps(SelectionKey.OP_READ); + } + } + } + + private Selector initSelector() throws IOException { + // Create a new selector + Selector socketSelector = SelectorProvider.provider().openSelector(); + + // Create a new non-blocking server socket channel + this.serverChannel = ServerSocketChannel.open(); + serverChannel.configureBlocking(false); + + // Bind the server socket to the specified address and port + InetSocketAddress isa = new InetSocketAddress(this.hostAddress, this.port); + serverChannel.socket().bind(isa); + + // Register the server socket channel, indicating an interest in + // accepting new connections + serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT); + + return socketSelector; + } + + public static void main(String[] args) { + try { + EchoWorker worker = new EchoWorker(); + new Thread(worker).start(); + new Thread(new NioServer(null, 9090, worker)).start(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file Added: sandbox/trunk/src/java/nio-server-example/README =================================================================== --- sandbox/trunk/src/java/nio-server-example/README (rev 0) +++ sandbox/trunk/src/java/nio-server-example/README 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1 @@ +From http://www.javafaq.nu/java-example-code-926.html Added: sandbox/trunk/src/java/nio-server-example/ServerDataEvent.java =================================================================== --- sandbox/trunk/src/java/nio-server-example/ServerDataEvent.java (rev 0) +++ sandbox/trunk/src/java/nio-server-example/ServerDataEvent.java 2009-09-21 06:04:40 UTC (rev 1474) @@ -0,0 +1,13 @@ +import java.nio.channels.SocketChannel; + +class ServerDataEvent { + public NioServer server; + public SocketChannel socket; + public byte[] data; + + public ServerDataEvent(NioServer server, SocketChannel socket, byte[] data) { + this.server = server; + this.socket = socket; + this.data = data; + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |