Introduction


Simple Network Framework for Java (SNF4J) is an asynchronous event-driven network application framework for quick and easy development of network applications.

The SNF4J serves as a simple, lightweight and independent network application framework helping in developing high performance and scalable network applications. It provides an asynchronous API via the Java NIO to handle various transports like TCP/IP, UDP/IP and SCTP/IP.

The framework is designed to be simple in use and moderately easy to understand. Application developers that like to keep their ear to the ground will not be overwhelmed by a tone of source code. It is oriented towards delivering core networking functionality as transferring data between two or more communicating network applications in a simple but effective way. To provide privacy and integrity of transferred data it provides support for the SSL/TLS/DTLS protocols.


Design

  • Unified API for transport layer types: TCP, UDP and SCTP
  • Event-driven API for developing asynchronous network applications
  • Customizable protocol engines for transport layer types: TCP and UDP
  • Utilities for development of UDP server applications
  • Simple API for customizable encoder-decoder pipelines
  • Provide ease of programing multi-thread applications in a single-thread way
  • Building pipelines of sessions sharing the same socket channel

Performance and Scalability

  • Support for minimized or even zero unnecessary memory copying
  • Support for low memory utilization in multi-session applications
  • Lower latency
  • zlib and gzip compression
  • Customizable selector loop pooling
  • Customizable byte buffer allocators

Thread model

  • All handler's events (i.e. read, event, timer, exception, incident) are fired from the thread that performs I/O for the channel (I/O thread)
  • All session's methods are thread-safe and can be called from any thread including the I/O thread and non-I/O threads
  • Any handler's event triggered as a side effect of calling a session's method are fired from the I/O thread
  • Codec's code is always processed in the I/O thread
  • Engine's code is always processed in the I/O thread

Supported Protocols

  • HTTP Web Proxy Connect Protocol
  • SOCKS Protocols
  • WebSocket Protocol
  • Toolkit NEW for TLS 1.3 Protocol (parsers/formatters, handshake engine, record layer utils and complete TLS engine)

Security

  • Complete support for SSL/TLS/DTLS protocols
  • Secure Web Proxy Connect

Integration

  • No additional dependencies, JDK 8 or JDK 9 (for DTLS) is enough
  • Fully customizable logging (SLF4J, Log4j 2 already here)
  • Customizable thread factories
  • Customizable session timers
  • Customizable packet retransmission models during DTLS handshakes

♦♦♦

How to...


This is only a very simple overview of the SNF4J API. It covers only basic concepts for implementing client and server networking applications with the SNF4J framework. More details can be found in the documentation and in the examples that are distributed along with the core source code.

Server side

Let's start with the server side. The first thing we have to do is create and start the selector loop that will process signals from the Java NIO.


SelectorLoop loop = new SelectorLoop();
loop.start();
    

Next, with the help of the Java NIO API we need to prepare a server socket channel that will handle incoming connections.


ServerSocketChannel channel = ServerSocketChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(PORT));
    

To implement server's logic we need to create a handler. It will be receiving events from the selector loop and data read from the socket channel.


public class ServerHandler extends AbstractStreamHandler {
    @Override
    public void read(Object msg) {
        //Some code
    }
}    
    

Now we are ready to register the server socket channel along with a session factory with the selector loop. From now on the server socket channel is ready for accepting incoming connections.


loop.register(channel, new AbstractSessionFactory() {
    @Override
    protected IStreamHandler createHandler(SocketChannel channel) {
        return new ServerHandler();
    }
});    
    

And finally, we can wait till the selector loop ends.


loop.join();
    

Client side

The server is running so let's waste no time and start implementing the client side. The first step looks familiar.


 SelectorLoop loop = new SelectorLoop();
 loop.start();
    

Next, with the help of the Java NIO API we need to prepare a client socket channel that will handle the connection.


SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(new InetSocketAddress(InetAddress.getByName(HOST), PORT));
    

To implement the client's logic we need to create a handler that will process session events and write some data to the server side. In the snippet below the client will send some nice words once connected with the server and then gently close. In addition it will instruct the selector loop to gently stop once the client session ends.


public class ClientHandler extends AbstractStreamHandler {

    @Override
    public void read(Object msg) {
        //Some code
    }
    
    @Override
    public void event(SessionEvent event) {
        switch (event) {
            case READY:
            getSession().write("Hello, World!".getBytes());
            getSession().close();
            break;
        }
    }

    @Override
    public ISessionConfig getConfig() {
        return new DefaultSessionConfig().setEndingAction(EndingAction.STOP);
    }
}
    

Now the hardest part is over so let's register with the selector loop.


loop.register(channel, new ClientHandler());
      

Finally, wait till the selector loop ends.


loop.join();
    

♦♦♦