package com.pekall.smartplug.test; import com.pekall.smartplug.codec.SmartPlugDecoder; import com.pekall.smartplug.codec.SmartPlugEncoder; import com.pekall.smartplug.message.BaseMessage; import com.pekall.smartplug.message.HelloRequest; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelEvent; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.ExceptionEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import java.net.InetSocketAddress; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; public class ClientMain { private static class ClientHandler extends SimpleChannelUpstreamHandler { // Stateful properties private volatile Channel channel; private final BlockingQueue<BaseMessage> answer = new LinkedBlockingQueue<BaseMessage>(); public BaseMessage getResponse(BaseMessage request) { channel.write(request); boolean interrupted = false; BaseMessage response; for (;;) { try { clog("before take"); response = answer.take(); clog("after take"); break; } catch (InterruptedException e) { interrupted = true; } } if (interrupted) { Thread.currentThread().interrupt(); } return response; } @Override public void handleUpstream( ChannelHandlerContext ctx, ChannelEvent e) throws Exception { if (e instanceof ChannelStateEvent) { clog(e.toString()); } super.handleUpstream(ctx, e); } @Override public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { channel = e.getChannel(); clog("channelOpen"); super.channelOpen(ctx, e); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { BaseMessage message = (BaseMessage) e.getMessage(); clog(message.toString()); boolean offered = answer.offer(message); assert offered; } @Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { clog("Unexpected exception from downstream."); e.getChannel().close(); } } private static final int SERVER_PORT = 8888; private static ClientBootstrap sClientBootstrap; private static Channel sClientChannel; private static void clog(String msg) { System.out.println("client --> " + msg); } private static void start() { // Set up. sClientBootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // Configure the event pipeline factory. sClientBootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { ChannelPipeline pipeline = Channels.pipeline(); pipeline.addLast("decoder", new SmartPlugDecoder()); pipeline.addLast("encoder", new SmartPlugEncoder()); pipeline.addLast("handler", new ClientHandler()); return pipeline; } }); // Make a new connection. ChannelFuture connectFuture = sClientBootstrap.connect(new InetSocketAddress("localhost", SERVER_PORT)); // Wait until the connection is made successfully. sClientChannel = connectFuture.awaitUninterruptibly().getChannel(); } private static void stop() { // Close the connection. sClientChannel.close().awaitUninterruptibly(); // Shut down all thread pools to exit. sClientBootstrap.releaseExternalResources(); } public static void main(String[] args) { start(); testHello(); } private static void testHello() { // Get the handler instance to initiate the request. ClientHandler handler = sClientChannel.getPipeline().get(ClientHandler.class); int messageId = 0; String deviceId = "123456789"; String deviceMode = "abcdefghi"; HelloRequest request = new HelloRequest(messageId, deviceId, deviceMode); // Request and get the response. clog("before getResponse"); BaseMessage response = handler.getResponse(request); clog("after getResponse"); clog(response.toString()); } }