Tengi
Near-Realtime Communication Foundation for Java / ActionScript / C# / HTML5 / and many more using Sockets, Websockets, HTTP2, HTTP Long-Polling
Install / Use
/learn @noctarius/TengiREADME
= tengi - Near-Realtime Communication Foundation Christoph Engelbert https://github.com/noctarius[@noctarius2k] // Settings: :compat-mode!: :idseparator: - // Aliases: :project-name: tengi README :project-handle: tengi-readme :toc:
image:https://badges.gitter.im/Join%20Chat.svg[link="https://gitter.im/noctarius/tengi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image:https://noctarius.ci.cloudbees.com/job/tengi/badge/icon[link="https://noctarius.ci.cloudbees.com/job/tengi"] image:https://codecov.io/github/noctarius/tengi/coverage.svg?branch=master[link="https://codecov.io/github/noctarius/tengi?branch=master"] image:https://img.shields.io/badge/license-Apache%20License%202-brightgreen.svg[link="http://www.apache.org/licenses/LICENSE-2.0"]
tengi is designed as a cross-language communication platform. Using several distinct transport layers, tengi always finds the most efficient way to communicate between the client and server. + Available transports range from a plain TCP transmission over RDP (a reliable UDP implementation), standard UDP or HTTP Long-Polling as fallback.
== Features === Cutting-Edge Technology
tengi implements industry standards like socket layer communication using TCP and UDP but also offers support cutting-edge technologies like SCTP and HTTP2 for future perspective. By transparently offering a variety of transportation layers using a common, flexible but simple and easy-to-use API, tengi is class-leading for the cross-language communication sector.
=== Simplicity driven APIs
The famous quote 'if you can't explain it to a six year old, you don't understand it yourself', by Albert Einstein, is not only true to Physics but also to software APIs. Complex APIs prevent people from using your solution or have a very flat learning curve and getting started is a hard task. +
Good APIs are easy readable, self explanatory and fast to get started with.
tengi, for this reason, hides complexity behind a simple but powerful API. An echo-server example is less than 20 lines of code but complex tasks can be achieved using a rich set of system-hooks for advanced users.
=== Data Protocol and Reliability
tengi's default protocol is a highly bandwidth optimized serialization and transmission solution. Supporting compressed int32 and int64 data types (when 64 bit types are supported by client languages) as well as providing way to serialize objects in custom way with guarantee of minimal overhead.
Depending on the selected transport layer additional overhead is necessary (e.g. HTTP, HTTP2). Due to the fact tengi always finds the best communication path, ending up using expensive transports is very unlikely. Still tengi supports communication through corporate firewalls and unreliable networks (e.g. mobile providers).
=== Asynchronous and Reactivity
Reactive design principles and event driven systems are most common way to start nowadays scalable solutions. Therefore tengi offers full support of the reactive pattern. From bottom up the internal implementation is completely based on a reactive design and this is also passed to the user.
=== Performance and the Java Power
More and more developers start using Java, or better said the JVM (Java Virtual Machine), as the foundation for their backend technologies. Powerful JIT (Just-In-Time) compilation and optimization based on runtime behavior bundled with the automatic resource management are a perfect base for server systems. In addition tengi is optimized for high performance, low latency and minimal Garbage Collector pressure.
Using latest Java 8 features like Closures (Lambdas), interface evolution and optimized data structures provides a compact and future-oriented external API.
=== Cross-Language Clients
tengi is designed to provide a simple communication protocol. The protocol specification is fully documented and easy to implement on further languages.
Currently planned clients include, but are not limited to, C#, C++, HTML5 (using ASM.js) and ActionScript, next to an obvious Java client.
== Getting Started
=== API Description
The Java API (JavaDoc) is available link:http://noctarius.github.io/tengi/[here].
=== Client Example
[source,java]
public void createEchoClient() { // Create configuration using the builder Configuration configuration = new ConfigurationBuilder() // Configure available transports .addTransport(ClientTransports.TCP_TRANSPORT, ClientTransports.HTTP_TRANSPORT)
// Build final configuration
.build();
// Create client instance using configuration Client client = Client.create(configuration);
// Connect to remote server client.connect("127.0.0.1", this::onConnect); }
private void onConnect(Connection connection) { connection.addMessageListener(this::onMessage);
Packet packet = new Packet("request"); packet.setValue("name", "Steven"); connection.writeObject(packet); }
private void onMessage(Connection connection, Message message) { Packet packet = message.getBody(); String helloWorld = packet.getValue("value"); System.out.println(helloWorld); }
=== Server Example
[source,java]
public void createEchoServer() { // Create configuration using the builder Configuration configuration = new ConfigurationBuilder() // Configure available transports .addTransport(ServerTransports.TCP_TRANSPORT, ServerTransports.HTTP2_TRANSPORT, ServerTransports.HTTP_TRANSPORT)
// Build final configuration
.build();
// Create server instance using configuration Server server = Server.create(configuration);
CompletableFuture<Channel> future = server.start(this::onConnect); }
private void onConnect(Connection connection) { connection.addMessageListener(this::onMessage); }
private void onMessage(Connection connection, Message message) { Packet packet = message.getBody(); String name = packet.getValue("name"); Packet response = new Packet("response"); response.setValue("value", "Hello World " + name); connection.writeObject(response); }
== Maven Coordinates
== Javadoc
== API Walkthrough
=== Configuration
=== Core
==== Transports
===== TCP
===== UDP
===== RDP
===== WebSocket
===== HTTP2
===== HTTP Long-Polling
==== Connection
==== Listener
===== MessageListener
===== ConnectionListener
===== ConnectionConnectedListener
==== Logging
==== Serialization
===== Packet
===== Marshallable
===== Marshaller and MarshallerFilter
===== Message
===== Debugging
=== Server
==== Transports
==== Server
==== Broadcaster
=== Client
==== Transports
==== Client
== Protocol Specification
This chapter describes the tengi internal default protocol and serialization techniques.
It contains information about the available built-in data types, their sizes and value ranges. In addition it describes the the protocol and packet headers, as well as definitions how compression and serialization of certain special types is handled.
The tengi default protocol is designed to be low overhead and any kind of object is expected as non-null by default. Values that can be null must be written explicitly and adding a marker byte to the stream.
[NOTE]
Even if most computer architecture these days as based on Little Endian, the protocol is completely implemented to the rules of Big Endian. If a system based on Little Endian encoding is used, conversion between Little Endian and Big Endian is necessary before writing or after reading the byte stream.
=== Codec (Encoder, Decoder)
The com.noctarius.tengi.serialization.codec.Codec class consists of two sub-interfaces which should never be implemented independently but always as a complete codec.
A Codec defines a way to serialize and de-serialize values of a predefined set of special built-in types and objects of various, user defined types.
tengi, by default, offers a low-overhead and fast codec implementation which is automatically picked up and instantiated.
The Codec provides reader and writer methods for the distinct data types and two methods to read or write objects. Codec::writeObject writes non-null objects and throws an exception when null is passed to the method. Codec::writeNullableObject offers an automatic way to handle values that possibly can be null. It adds an extra Byte to the stream to mark the value to be null or not.
=== Data Types
.Built In DataTypes |=== | Name | Java | Length | Min | Max | Note
| Byte | byte | 8 Bit | -128 | 127 |
| Unsigned Byte | short | 8 Bit | 0 | 255 |
| Byte-Array | byte[] | 8 Bit per index | | |
| Short | short | 16 Bit | −32,768 | 32,767 |
| Char | char | 16 Bit | \u0000 (0) | \uffff (65,535) |
| Int32 | int | 32 Bit | -2^31^ | -2^31^ - 1 |
| Compressed Int32 | int | 8 Bit - 40 Bit | -2^31^ | -2^31^ - 1 | <<int32-compression,Int32 Compression>>
| Int64 | long | 64 Bit | -2^63^ | 2^63^ - 1 |
| Compressed Int64 | long | 8 Bit - 72 Bit | -2^63^ | 2^63^ - 1 | <<int64-compression,Int64 Compression>>
| Float | float | 32 Bit | ±1.4e^-45^ | ±3.4028235e^38^ | Single-precision IEEE 754 floating point
| Double | double | 64 Bit | ±4.9e^-324^ | ±1.7976931348623157e^308^ | Double-precision IEEE 754 floating point
| Boolean | boolean | 1 Bit | false | true | Written as 8 Bit
| BitSet | boolean[] | 1 Bit | false | true | BitSet Compression explained below
| String | String | 32 Bit length, + content | | | UTF-8 encoded content
| Identifier | Identifier | 128 Bit | | | Optimized UUIDv4
|===
==== Byte
==== Unsigned Byte
==== Byte-Array
==== Short
==== Char
==== Int32
==== Int64
==== Float
==== Double
==== Boolean
==== Identifier
=== Int32 Compression
The Int32 Compression can be used to write Int32 values that are expected to be quite small in most cases but might exceed the range of smaller data types in certain cases.
[NOTE]
Int32 Compression is not supported per Encoder::writeObject but needs to be used explicitly us
