Question

Server

import java.util.concurrent.atomic.AtomicReference;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
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.handler.codec.spdy.DefaultSpdySynStreamFrame;

public class SpdyChannelUpStreamHandler extends SimpleChannelUpstreamHandler {
volatile Channel channel;
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();

@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
        throws Exception {
    System.out.println("Channel In Open Stage");
    channel = e.getChannel();

}

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
        throws Exception {
    System.out.println("Channel In Connected Stage");
    Channels.write(channel, new DefaultSpdySynStreamFrame(1, 1, (byte)0));
}

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
        throws Exception {
    System.out.println("Message Received on Server Side");
     Channels.write(channel, e.getMessage(), e.getRemoteAddress());
}


@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
        throws Exception {
     if (exception.compareAndSet(null, e.getCause())) {
         e.getChannel().close();
     }
}

}

import static org.jboss.netty.channel.Channels.pipeline;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.spdy.SpdyFrameDecoder;
import org.jboss.netty.handler.codec.spdy.SpdyFrameEncoder;
import org.jboss.netty.handler.codec.spdy.SpdySessionHandler;

public class SpdyPipeLineFactory implements ChannelPipelineFactory{

@Override
public ChannelPipeline getPipeline() throws Exception {
    ChannelPipeline pipeline = pipeline();
    pipeline.addLast("decoder", new SpdyFrameDecoder(2));
    pipeline.addLast("encoder", new SpdyFrameEncoder(2));
    //pipeline.addLast("sessionHandler",new SpdySessionHandler(2,true));
    pipeline.addLast("handler", new SpdyChannelUpStreamHandler());
    return pipeline;
}

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class StartServer {
public static void main(String[] args){
ServerBootstrap bootStrapServer = new ServerBootstrap(new 
        NioServerSocketChannelFactory(Executors.newCachedThreadPool(), 
        Executors.newCachedThreadPool()));
    bootStrapServer.setPipelineFactory(new SpdyPipeLineFactory());
    bootStrapServer.bind(new InetSocketAddress(8443));
}


}

This is SPDY enabled server example that I was able to put together using netty libraries by reading at multiple places on the internet. When I run this server and Connect using SPDY client ,My connection is successful because I can see the messages in the function that channelOpen and channelConnected.

There are couple questions that I want to ask as I have very limited understanding of SPDY protocol. I will start with the first thing that I want to do.

1 - How can server sends the messages to client , currently I do this in channelConnected method which I can see on the client side , but that gives me very limited chance to send the message and channelConnected event happens once during the Channel Setup process ,

is there any way to get the handle to currently all open channel on SPDY server and identify these channels so that I could select the channels on demand and use them to send the messages?

Was it helpful?

Solution

Your best bet is to create a shared ChannelGroup and whenever a new channel connects, add the channel to the ChannelGroup. You will need to figure out how to identify the channel you want to send to based on the channel meta-data available (such as remote address or channel ID). Then you can retrieve the channel from the ChannelGroup and write messages to it. Additional advantages of the ChannelGroup are

  • When channels close, they are automatically removed from the ChannelGroup.
  • You can call close on the ChannelGroup to close all the contained channels.
  • You can invoke writes on the ChannelGroup to to write a message to all the contained channels.

I wrote an extended Channel wrapper so I can associate additional meta-data to a channel. Part of my protocol is that when a new channel connects, I send it a WHO message and the client responds with some client-identity values which I add to the channel wrapper. I also implemented a JMX interface that exposes the channels in the group so I can see exactly what clients are connected.

Screen shot of enhanced channel meta-data in JConsole

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top