/** Notify this server's consumers that the server has started. */ protected void notifyStart(final Runnable started) { getReactor().notify(start.getObject(), selfEvent); if (null != started) { getReactor() .schedule( new Consumer<Runnable>() { @Override public void accept(Runnable r) { r.run(); } }, started); } }
/** Notify this server's consumers that the server has stopped. */ protected void notifyShutdown() { getReactor().notify(shutdown.getObject(), selfEvent); }
/** * Notify this peer's consumers that the given channel has been closed. * * @param channel The channel that was closed. */ protected void notifyClose(@Nonnull NetChannel<IN, OUT> channel) { reactor.notify(close.getObject(), Event.wrap(channel)); }
/** * Notify this peer's consumers that the channel has been opened. * * @param channel The channel that was opened. */ protected void notifyOpen(@Nonnull NetChannel<IN, OUT> channel) { reactor.notify(open.getObject(), Event.wrap(channel)); }
public static void main(String[] args) throws Exception { Environment env = new Environment(); final TradeServer server = new TradeServer(); // Use a Reactor to dispatch events using the high-speed Dispatcher final Reactor serverReactor = Reactors.reactor(env); // Create a single key and Selector for efficiency final Selector tradeExecute = Selectors.object("trade.execute"); // For each Trade event, execute that on the server and notify connected clients // because each client that connects links to the serverReactor serverReactor.on( tradeExecute, (Event<Trade> ev) -> { server.execute(ev.getData()); // Since we're async, for this test, use a latch to tell when we're done latch.countDown(); }); @SuppressWarnings("serial") WebSocketServlet wss = new WebSocketServlet() { @Override public void configure(WebSocketServletFactory factory) { factory.setCreator( (req, resp) -> new WebSocketListener() { AtomicLong counter = new AtomicLong(); @Override public void onWebSocketBinary(byte[] payload, int offset, int len) {} @Override public void onWebSocketClose(int statusCode, String reason) {} @Override public void onWebSocketConnect(final Session session) { LOG.info("Connected a websocket client: {}", session); // Keep track of a rolling average final AtomicReference<Float> avg = new AtomicReference<>(0f); serverReactor.on( tradeExecute, (Event<Trade> ev) -> { Trade t = ev.getData(); avg.set((avg.get() + t.getPrice()) / 2); // Send a message every 1000th trade. // Otherwise, we completely overwhelm the browser and network. if (counter.incrementAndGet() % 1000 == 0) { try { session .getRemote() .sendString(String.format("avg: %s", avg.get())); } catch (IOException e) { if (!"Failed to write bytes".equals(e.getMessage())) { e.printStackTrace(); } } } }); } @Override public void onWebSocketError(Throwable cause) {} @Override public void onWebSocketText(String message) {} }); } }; serve(wss); LOG.info( "Connect websocket clients now (waiting for 10 seconds).\n" + "Open websocket/src/main/webapp/ws.html in a browser..."); Thread.sleep(10000); // Start a throughput timer startTimer(); // Publish one event per trade for (int i = 0; i < totalTrades; i++) { // Pull next randomly-generated Trade from server Trade t = server.nextTrade(); // Notify the Reactor the event is ready to be handled serverReactor.notify(tradeExecute.getObject(), Event.wrap(t)); } // Stop throughput timer and output metrics endTimer(); server.stop(); }