Assume we have two services: add and sub, which are responsible for adding and subtracting passed integer values. The services protocol could be descibed by the following ABNF:
add
protocol = magic value1 value2 magic = "add" value1 = INT value2 = INT INT = 4*BYTE BYTE = OCTET
sub
protocol = magic value1 value2 magic = "sub" value1 = INT value2 = INT INT = 4*BYTE BYTE = OCTET
From the protocol description, it's obvious we can distinguish two services and their protocols by 3-bytes magic header, add-service has "add", sub-service "sub". So it's what service's ProtocolFinder should address. For example add-service ProtocolFinder may look like:
/** * {@link ProtocolFinder}, responsible to determine if incoming byte buffer * represents ADD-service request. */ public class AddProtocolFinder implements ProtocolFinder { private final static byte[] magic = {'a', 'd', 'd'}; /** * {@inheritDoc} */ @Override public Result find(final PUContext puContext, final FilterChainContext ctx) { // Get the input Buffer final Buffer inputBuffer = ctx.getMessage(); final int bytesToCompare = Math.min(magic.length, inputBuffer.remaining()); final int bufferStart = inputBuffer.position(); // Compare incoming bytes with ADD-service protocol magic for (int i = 0; i < bytesToCompare; i++) { if (magic[i] != inputBuffer.get(bufferStart + i)) { // If at least one byte doesn't match - it's not ADD-service protocol return Result.NOT_FOUND; } } // if we check entire magic - return FOUND, or NEED_MORE_DATA otherwise return bytesToCompare == magic.length ? Result.FOUND : Result.NEED_MORE_DATA; } }
The add-service FilterChain will contain two Filters:
AddServerMessageFilter, responsible for parsing/serializing add-service messages
AddServiceFilter the actual service implementation
The PUProtocol initialization and registration for add-service will look following way:
// Create PUFilter final PUFilter puFilter = new PUFilter(); // Create ADD-service ProtocolFinder final ProtocolFinder addProtocolFinder = new AddProtocolFinder(); // Create ADD-service FilterChain final FilterChain addProtocolFilterChain = puFilter.getPUFilterChainBuilder() // Add ADD-service message parser/serializer .add(new AddServerMessageFilter()) // Add ADD-service filter .add(new AddServiceFilter()) .build(); // Construct PUProtocol final PUFilter addServicePUProtocol = new PUProtocol(addProtocolFinder, addProtocolFilterChain); // Register add-service pu protocol puFilter.register(addServicePUProtocol);
Similar coding is required for the sub-service. Finally port unification Filter (PUFilter) should be added to the main FilterChain and Transport could be started
// Construct the main filter chain final FilterChainBuilder puFilterChainBuilder = FilterChainBuilder.stateless() .add(new TransportFilter()) .add(puFilter); // Build TCP transport final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build(); transport.setProcessor(puFilterChainBuilder.build()); // Bind to the server port transport.bind(PORT); // Start transport.start();
Complete sample code could be found here.