Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demo simplified and slightly expanded #6

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
socket-ntp
socket-ntp-krcmod
==========

NTP Sync using Socket.io. Allows you to sync clients against a server by calculating the time offset.
NTP Sync using Socket.io. Provides current time on webserver as well as the client offset from the webserver.

My take on Calvin French-Owen (calvinfo)'s concise socket-ntp. Can be used as a drop-in replacement.

I used the basic framework and made it needlessly more complicated :)

* Lower ping times are valued over higher since there's less chance of error in the NTP calculation
* Interrogates strong for 20 seconds, then throttles back to preserve resources
* added ntp.serverTime() for us lazybones
* Demo: Streamlined the express code. Added a primitive scheduler for synchronizing events across multiple nodes
* Demo: Socket.io client switched to the one automatically served by socket.io
* Demo: We didn't really need jQuery in there


## Installation

```
npm install socket-ntp
npm install socket-ntp-krcmod
```
Requires access to [socket.io](http://socket.io/) connections on both the client and the server.


## Client usage

On the client, include:

```html
<script src="/javascripts/libs/socket.io.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/client/ntp.js"></script>
```

Expand All @@ -24,15 +37,16 @@ On the client, include:
var socket = io.connect();
ntp.init(socket);

var offset = ntp.offset(); // time offset from the server in ms
var offset = ntp.offset(); // time offset from the server in ms
var servertime = ntp.serverTime(); //what time is it on the server (equivalent to Date.now())
```

## Server usage

From anywhere that you have access to a socket.io instance.

```javascript
var ntp = require('socket-ntp');
var ntp = require('socket-ntp-krcmod');

io.sockets.on('connection', function (socket) {
ntp.sync(socket);
Expand Down Expand Up @@ -70,4 +84,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
93 changes: 59 additions & 34 deletions client/ntp.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,75 @@
(function (root) {

var ntp = {}
, offsets = []
, socket;
var ntp = {}
, offsets = []
, socket;

ntp.init = function (sock, options) {
options = options || {};
ntp.init = function (sock) {
socket = sock;
socket.on('ntp:server_sync', onSync);
sync();
};

socket = sock;
socket.on('ntp:server_sync', onSync);
setInterval(sync, options.interval || 1000);
};
var onSync = function (data) {

var onSync = function (data) {
var diff = Date.now() - data.t1 - ((Date.now() - data.t0)/2);
var ping = Date.now() - data.t0;
offsets.unshift([ping,diff]);

var diff = Date.now() - data.t1 + ((Date.now() - data.t0)/2);
if (offsets.length > 20){
offsets.pop();
}

offsets.unshift(diff);
};

if (offsets.length > 10)
offsets.pop();
};
ntp.offset = function () {
var sum = 0;
var offsetsSorted = offsets.slice(0); //make a copy of the offsets array for sorting. Keep the original so the times keep cycling.
offsetsSorted.sort(sort2dArray);

if (offsetsSorted.length >4){ //get rid of everything except the 4 lowest ping times.
for (var i = 0; i < offsets.length-3; i++) {
offsetsSorted.pop();
}
}
for (var i = 0; i < offsetsSorted.length; i++) { //add up and average the 4 offset times associated with the lowest ping times
sum += offsetsSorted[i][1];
}

ntp.offset = function () {
var sum = 0;
for (var i = 0; i < offsets.length; i++)
sum += offsets[i];
sum /= offsetsSorted.length;
return sum;
};

sum /= offsets.length;
ntp.serverTime = function () {
return Math.round(Date.now() -ntp.offset());
};

return sum;
};
var sync = function () {
socket.emit('ntp:client_sync', { t0 : Date.now() });
//console.log(ntp.offset() + " is the current offset");
if (offsets.length <19){ //every second for the first 20, every 5 after. To reduce network traffic.
setTimeout(function(){sync();}, 1000)
} else{
setTimeout(function(){sync();}, 5000)
}
};

var sort2dArray = function (a, b) { //for sorting the 2d array by ping time
if (a[0] === b[0]) {
return 0;
}
else {
return (a[0] < b[0]) ? -1 : 1;
}
}

var sync = function () {
socket.emit('ntp:client_sync', { t0 : Date.now() });
};

// AMD/requirejs
if (typeof define === 'function' && define.amd) {
define('ntp', [], function () {
return ntp;
});
} else {
root.ntp = ntp;
}
// AMD/requirejs
if (typeof define === 'function' && define.amd) {
define('ntp', [], function () {
return ntp;
});
} else {
root.ntp = ntp;
}

})(window);
2 changes: 0 additions & 2 deletions client/socket.io.min.js

This file was deleted.

37 changes: 7 additions & 30 deletions example/app.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,20 @@

var fs = require('fs')
, path = require('path')
, http = require('http')
var http = require('http')
, express = require('express')
, socketio = require('socket.io')
, ntp = require('../');


var app = express()
, server = http.createServer(app)
, io = socketio.listen(server);
DEBUG=''; //turn off heartbeat messages, socket.io 1.10 and later


app.get('/', function (req, res) {

var file = path.resolve(__dirname, './index.html');

fs.createReadStream(file).pipe(res);
});


app.get('/client/:filename', function (req, res, next) {

debugger;

var filename = req.param('filename')
, filepath = path.resolve(__dirname, '../client/', filename);

fs.exists(filepath, function (exists) {

if (exists)
fs.createReadStream(filepath).pipe(res);
else
res.send(404, 'Page not found!');
});
});

app.use(express.static(__dirname));
app.use('/client', express.static('../client/'));

io.sockets.on('connection', ntp.sync);

server.listen(80);

console.log ("Starting application on *:80");

server.listen(3000);
25 changes: 14 additions & 11 deletions example/index.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="/client/socket.io.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="/client/ntp.js"></script>

<script>

var socket = io.connect();

ntp.init(socket);
setInterval(function () {
$('#offset').text(ntp.offset());
}, 1000);
var socket = io.connect();
ntp.init(socket);

setInterval(function () {
setTimeout(function(){
document.getElementById("offset").innerHTML= "Server time: " + ntp.serverTime(); //what time the server thinks it is
document.getElementById("offset").innerHTML+= "<p>Offset: " + ntp.offset();

},( 1000-(Date.now() - ntp.offset())%1000));//update the display at our guess of where the server thinks a new second occurs
},1000);

</script>


</head>
<body>
<span id="offset"></span>

</body>
</html>
17 changes: 12 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
{
"name": "socket-ntp",
"version": "0.1.0",
"name": "socket-ntp-krcmod",
"version": "0.2.0",
"main": "lib/ntp",
"description": "NTP syncing algorithm between client and server using socket.io",
"description": "Enhanced NTP syncing algorithm between client and server using socket.io",
"keywords": ["ntp", "socket", "socket.io"],
"author": "Calvin French-Owen <[email protected]>",
"contributors": [{
"name": "Ross Brackett",
"email": "[email protected]"
}],
"scripts": {
"start": "node example/app.js"
},
"devDependencies": {
"express": "3.0.2",
"express": ">=3.0.2",
"socket.io": "*"
},
"homepage": "https://github.com/karaokeresearch/socket-ntp-krcmod",
"bugs": "https://github.com/karaokeresearch/socket-ntp-krcmod/pulls",
"license": "MIT",
"repository": {
"type": "git",
"url": "[email protected]:calvinfo/socket-ntp.git"
"url": "[email protected]:karaokeresearch/socket-ntp-krcmod.git"
}
}