Skip to content
itzstonlex edited this page Jan 31, 2022 · 11 revisions

RECON

Protocol and Remote Connection management

Latest version release: 1.0.0

MIT License


What is this?

Recon - most simple and simplified library for implementing protocol applications, remote data transfer and remote connections with servers, sites, etc.

This is a single API association and many auxiliary modules for both simplifying the code and for new functionality.


Use & Installation

Download the necessary libraries from this folder and install them into your project through artifacts, local repositories, or any other methods convenient for you.


Tests

If something of what was said below was not clear to you, then you can refer to the tests, which were the source of information and code: Click to redirect


How to create remote connection?

Server Examples:

import org.itzstonlex.recon.side.Server;
import org.itzstonlex.recon.RemoteChannel;

public class ServerConnection {

    public static final int BIND_PORT = 1010;

    public void launchApplication() {
        Server server = new Server();
        
        RemoteChannel serverChannel = server.bindLocal(BIND_PORT);
    }

    // That method running from manifest classpath.
    public static void main(String[] args) {
        ServerConnection serverConnection = new ServerConnection();
        serverConnection.launchApplication();
    }
}

Client Examples:

import org.itzstonlex.recon.side.Client;
import org.itzstonlex.recon.RemoteChannel;

public class ClientConnection {

    public static final int CONNECT_PORT = 1010;

    public void launchApplication() {
        Client client = new Client();
        
        RemoteChannel clientChannel = client.connectLocal(CONNECT_PORT);
    }

    // That method running from manifest classpath.
    public static void main(String[] args) {
        ClientConnection clientConnection = new ClientConnection();
        clientConnection.launchApplication();
    }
}

Events Listening

Listening for events makes it possible to notice changes in time and perform the necessary processes related to channels and processing bytes

Server Examples:

import org.itzstonlex.recon.ContextHandler;
import org.itzstonlex.recon.RemoteChannel;
import org.itzstonlex.recon.adapter.ChannelListenerAdapter;

import java.net.InetSocketAddress;

public class ServerChannelListener extends ChannelListenerAdapter {

    @Override
    public void onBind(RemoteChannel channel, ContextHandler contextHandler) {
        InetSocketAddress address = contextHandler.channel().address();
      
        ReconLog log = contextHandler.channel().logger();
        
        if (contextHandler.isSuccess()) {
            log.info("[Server] Connection was success bind on " + address);
            
        } else {
            
            log.info("[Server] Could not bind on " + address);
        }
    }
  
    @Override
    public void onClosed(RemoteChannel channel, ContextHandler contextHandler) {
        contextHandler.channel().logger().info("[Server] Connection is closed!");
    }
  
    @Override
    public void onExceptionCaught(RemoteChannel channel, Throwable throwable) {
        throwable.printStackTrace();
    }
}

Listeners are registered via ChannelPipeline as follows:

Server server = new Server();
server.bindLocal(BIND_PORT, config -> {
    
    config.pipeline().putLast("channel-handler", new ServerChannelListener());
    ...
});

Some of the available events work on specific sides of the connection:

  • Client:

    • onConnected(RemoteChannel, ContextHandler)
    • onConnectTimeout(RemoteChannel, ContextHandler)
  • Server:

    • onBind(RemoteChannel, ContextHandler)
    • onClientConnected(RemoteChannel, ContextHandler)
    • onClientClosed(RemoteChannel, ContextHandler)
  • For all:

    • onThreadActive(RemoteChannel, ContextHandler)
    • onClosed(RemoteChannel, ContextHandler)
    • onRead(RemoteChannel, ContextHandler, ByteStream.Input)
    • onWrite(RemoteChannel, ContextHandler, ByteStream.Output)
    • onExceptionCaught(RemoteChannel, Throwable)

Bytes Write

Create a bytes-buffer:

ByteStream.Output output = BufferFactory.createPooledOutput();

Put a data as bytes:

output.writeString("ItzStonlex");
output.writeBoolean(true);

And write to connection channel:

server.channel().write(output);

Method RemoteChannel#write(ByteStream.Output) write a bytes to all connected channels

Sending bytes can be intercepted using OutgoingByteHandler#onWrite()

For example:

import org.itzstonlex.recon.ByteStream;
import org.itzstonlex.recon.ContextHandler;
import org.itzstonlex.recon.RemoteChannel;
import org.itzstonlex.recon.handler.OutgoingByteHandler;

import java.util.Arrays;

public class WriteHandler extends OutgoingByteHandler {

    @Override
    public void onWrite(RemoteChannel channel, ContextHandler contextHandler,
                        ByteStream.Output buffer) {

        byte[] bytes = buffer.array();

        // ...handle bytes write
        channel.logger().info("onWrite: [bytes]:" + Arrays.toString(bytes));
    }
}

Bytes Read

Reading bytes is handled through IncomingByteHandler#onRead()

For example:

import org.itzstonlex.recon.ByteStream;
import org.itzstonlex.recon.ContextHandler;
import org.itzstonlex.recon.RemoteChannel;
import org.itzstonlex.recon.factory.BufferFactory;
import org.itzstonlex.recon.handler.IncomingByteHandler;

import java.util.Arrays;

public class ReadHandler extends IncomingByteHandler {

    @Override
    public void onRead(RemoteChannel channel, ContextHandler contextHandler,
                       ByteStream.Input buffer) {
        
        byte[] bytes = buffer.array();
        
        // ...read or handle bytes
        channel.logger().info("onRead: [bytes]:" + Arrays.toString(bytes));
    }
}

ReadHandler and WriteHandler are registered exactly the same way through the ChannelPipeline, like all other event handlers for channels, because they inherit the ChannelListener interface


Client Reconnection

The Recon library has functionality for reconnecting clients to a crashed server

To do this, it is enough to use one method, which adds a special listener to check the data it needs and start the reconnection task.

IMPORTANT! This method works exclusively for clients.

Client client = new Client();

RemoteChannel clientChannel = client.connectLocal(CONNECT_PORT, config -> {

    // add reconnect listener.
    ClientReconnectionUtils.setDebug(true);
    ClientReconnectionUtils.addReconnector(config.pipeline(), 5, TimeUnit.SECONDS);
});

Simplify You Code in Just One Line

ReconSimplify is a built-in Recon utility that will reduce the use of basic functionality in just one line.

Strongly advises you to read it yourself, because it contains many variations of solving problems that could be the same.

You can view the test package by following this link.