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 = OCTETsub
protocol = magic
value1
value2
magic = "sub"
value1 = INT
value2 = INT
INT = 4*BYTE
BYTE = OCTETFrom 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.