The connectanum Java WebSocket Server is a full featured WAMP router and client that implements most important advanced features for enterprise project development.
Connectanum uses WebSockets to connect browsers to a distributed, multi language business logic. Hereby it is possible to build a loosely coupled distributed computing network.
A WebSocket connection cannot be used without a sophisticated subprotocol. Connectanum offers support for distributed remote procedure calls (RPC) as well as the publish/subscribe pattern. Reactivity as known from AngularJS or ReactJs may not just be a part of your browser framework. With connectanum it is possible to have this kind of reactivity throughout your whole system.
The animation shows how multiple clients are connected to the connectanum router. Messages are getting forwarded between those clients by using remote procedure calls and publish events.
Connectanum offers interfaces for nearly every part of the core system. It was developed to be highly customizable and extensible by it's nature. Most of all methods have descriptions on how to use them.
The CodeIt is based on Netty NIO-Classes (non blocking) that drive nearly all professional Java frameworks for distributed systems. A flat router logic and header only message parsing causes a very low computing cost even for long messages.
Try YourselfThe Router has no business logic. Clients are scalable by their nature. Every route has a scalability option (Round Robin, First, Last, Random) and routing logic is non-blocking. The behaviour can be configured for each separate procedure.
FeaturesThis demo uses the following environment:
Browser (Client 1 + Client 2)
Connectanum (Router)
The connectanum server runs pretty fast and can handle hundreds of messages per second even on this very low performing server. You may see RTT < 20ms depending on your connection and your latencies. We have measured >=9ms in a local environment on this raspberry pi. Higher latencies may most probably be caused by the network bandwidth and latency.
Round trip time for the last message: ms
Round trip time for the last message: ms
angular.module('connectanum', ['connectanum.services'])
.controller("DemoCtrl",["$scope","Wamp", function ($scope, Wamp) {
$scope.client1 = Wamp.getInstance();
$scope.client2 = Wamp.getInstance();
var topic = "demo.connectanum.receive";
function initialize(client){
if(client.getSession()){
client.getSession().subscribe(topic, function (args) {
client.lastMessage = args[0];
client.roundTripMs = (new Date()).getTime() - args[1];
$scope.$$phase || $scope.$apply();
});
}
}
$scope.sendMessageTo1 = function (message) {
$scope.client2.getSession().publish(topic,[message,(new Date()).getTime()],{},{eligible:[$scope.client1.getSession().id]})
};
$scope.sendMessageTo2 = function (message) {
$scope.client1.getSession().publish(topic,[message,(new Date()).getTime()],{},{eligible:[$scope.client2.getSession().id]})
};
$scope.$on("wamp.connected", function (event,client) {
client.loginSuccess = true;
initialize(client);
$scope.$$phase || $scope.$apply();
});
$scope.$on("wamp.closed", function (event,client) {
client.loginSuccess = false;
$scope.$$phase || $scope.$apply();
});
$scope.login = function () {
$scope.client1.login("demo","demo");
$scope.client2.login("demo","demo");
};
$scope.logout = function () {
$scope.client1.logout();
$scope.client2.logout();
}
}])
;
angular.module('connectanum.services', [])
.factory("Wamp", ["$rootScope",function ($rootScope) {
var Wamp = function(){
this._session = null;
this._details = null;
};
Wamp._connector = autobahn.Connection;
Wamp.prototype = {
login : function (username,password) {
var self = this;
$rootScope.$broadcast("wamp.loggingIn",username);
this._connection = new Wamp._connector({
url:"wss://www.connectanum.com/wamp",
realm:"de.konsultaner.middleware.demo",
authmethods:["wampcra"],
authid: username,
onchallenge: (function (password) {
return function (session, method, extra) {
$rootScope.$broadcast("wamp.challenge",session);
if (method === "wampcra") {
return autobahn.auth_cra.sign(
autobahn.auth_cra.derive_key(password || "", extra.salt,extra.iterations,extra.keylen),
extra.challenge
);
}
}
})(password)
});
this._connection.onopen = function (session) {
self._session = session;
$rootScope.$broadcast("wamp.connected",self);
};
this._connection.onclose = function (reason,details) {
$rootScope.$broadcast("wamp.closed",self);
if(reason === "closed"){
if(details.reason === "wamp.error.authorization_failed"){
$rootScope.$broadcast("wamp.closed.authorization_failed",details);
}else{
$rootScope.$broadcast("wamp.closed.normal",details);
}
}else if(reason === "lost"){
$rootScope.$broadcast("wamp.closed.lost",details);
}else if(reason === "unreachable"){
$rootScope.$broadcast("wamp.closed.unreachable",details);
}else if(reason === "unsupported"){
$rootScope.$broadcast("wamp.closed.unsupported",details);
}
this._session = null;
};
this._connection.open();
},
logout : function () {
this._connection.close();
this._session = null;
},
getSession : function () {
return this._session;
}
};
return new (function () {
this.getInstance = function () {
return new Wamp();
}
});
}])
;