2011-01-19 21:25:44 +00:00
|
|
|
<html>
|
|
|
|
|
|
|
|
<head>
|
|
|
|
<title>WebSockets Latency Test</title>
|
|
|
|
<script src="include/base64.js"></script>
|
|
|
|
<script src="include/util.js"></script>
|
|
|
|
<script src="include/webutil.js"></script>
|
2011-01-24 01:30:51 +00:00
|
|
|
<script src="include/websock.js"></script>
|
2011-01-19 21:25:44 +00:00
|
|
|
<!-- Uncomment to activate firebug lite -->
|
|
|
|
<!--
|
|
|
|
<script type='text/javascript'
|
|
|
|
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
|
|
|
-->
|
|
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
Host: <input id='host' style='width:100'>
|
|
|
|
Port: <input id='port' style='width:50'>
|
|
|
|
Encrypt: <input id='encrypt' type='checkbox'>
|
|
|
|
<br>
|
|
|
|
Payload Size: <input id='payload_size' style='width:50'>
|
|
|
|
Send Delay (ms): <input id='sendDelay' style='width:50' value="10">
|
|
|
|
<input id='connectButton' type='button' value='Start' style='width:100px'
|
|
|
|
onclick="connect();">
|
|
|
|
|
|
|
|
<br><br>
|
|
|
|
<table border=1>
|
|
|
|
<tr>
|
|
|
|
<th align="right">Packets sent:</th>
|
|
|
|
<td align="right"><div id='sent'></div></td>
|
|
|
|
</tr><tr>
|
|
|
|
<th align="right">Packets Received:</th>
|
|
|
|
<td align="right"><div id='received'></div></td>
|
|
|
|
</tr><tr>
|
|
|
|
<th align="right">Average Latency:</th>
|
|
|
|
<td align="right"><div id='laverage'></div></td>
|
|
|
|
</tr><tr>
|
|
|
|
<th align="right">40 Frame Running Average Latency:</th>
|
|
|
|
<td align="right"><div id='lrunning'></div></td>
|
|
|
|
</tr><tr>
|
|
|
|
<th align="right">Minimum Latency:</th>
|
|
|
|
<td align="right"><div id='lmin'></div></td>
|
|
|
|
</tr><tr>
|
|
|
|
<th align="right">Maximum Latency:</th>
|
|
|
|
<td align="right"><div id='lmax'></div></td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<br>
|
|
|
|
Messages:<br>
|
|
|
|
<textarea id="messages" style="font-size: 9;" cols=80 rows=10></textarea>
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
2011-01-24 01:30:51 +00:00
|
|
|
var host = null, port = null, sendDelay = 0, actualSendDelay,
|
2011-01-19 21:25:44 +00:00
|
|
|
ws = null, send_ref = null,
|
|
|
|
sent, received, latencies, ltotal, laverage, lrunning, lmin, lmax,
|
|
|
|
run_length = 40,
|
|
|
|
payload_size = 2000, payload,
|
|
|
|
msg_cnt = 0, recv_seq = 0, send_seq = 0;
|
|
|
|
|
|
|
|
Array.prototype.pushStr = function (str) {
|
|
|
|
var n = str.length;
|
|
|
|
for (var i=0; i < n; i++) {
|
|
|
|
this.push(str.charCodeAt(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function message(str) {
|
|
|
|
console.log(str);
|
|
|
|
cell = $D('messages');
|
|
|
|
msg_cnt++;
|
|
|
|
cell.innerHTML += msg_cnt + ": " + str + "\n";
|
|
|
|
cell.scrollTop = cell.scrollHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function add (x,y) {
|
2011-01-24 01:30:51 +00:00
|
|
|
return parseInt(x,10)+parseInt(y,10);
|
|
|
|
}
|
2011-01-19 21:25:44 +00:00
|
|
|
|
|
|
|
function recvMsg(data) {
|
|
|
|
//console.log(">> check_respond");
|
2011-01-24 01:30:51 +00:00
|
|
|
var i, now, arr, first, last, arr, latency;
|
2011-01-19 21:25:44 +00:00
|
|
|
|
|
|
|
now = (new Date()).getTime(); // Early as possible
|
|
|
|
|
2011-01-24 01:30:51 +00:00
|
|
|
arr = ws.rQshiftBytes(ws.rQlen());
|
|
|
|
first = String.fromCharCode(arr.shift());
|
|
|
|
last = String.fromCharCode(arr.pop());
|
2011-01-19 21:25:44 +00:00
|
|
|
|
|
|
|
if (first != "^") {
|
|
|
|
message("Error: packet missing start char '^'");
|
|
|
|
disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (last != "$") {
|
|
|
|
message("Error: packet missing end char '$'");
|
|
|
|
disconnect();
|
|
|
|
return;
|
|
|
|
}
|
2011-01-24 01:30:51 +00:00
|
|
|
arr = arr.map(function(num) {
|
2011-01-19 21:25:44 +00:00
|
|
|
return String.fromCharCode(num);
|
|
|
|
} ).join('').split(':');
|
|
|
|
seq = arr[0];
|
|
|
|
timestamp = parseInt(arr[1],10);
|
|
|
|
rpayload = arr[2];
|
|
|
|
|
|
|
|
if (seq != recv_seq) {
|
|
|
|
message("Error: expected seq " + recv_seq + " but got " + seq);
|
|
|
|
disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
recv_seq++;
|
|
|
|
if (payload !== rpayload) {
|
|
|
|
message("Payload corrupt");
|
|
|
|
disconnect();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
received++;
|
|
|
|
|
|
|
|
latency = now - timestamp;
|
|
|
|
latencies.push(latency);
|
|
|
|
if (latencies.length > run_length) {
|
|
|
|
latencies.shift();
|
|
|
|
}
|
|
|
|
ltotal += latency;
|
|
|
|
laverage = ltotal / received;
|
|
|
|
lrunning = 0;
|
|
|
|
for (var i=0; i < latencies.length; i++) {
|
|
|
|
lrunning += latencies[i];
|
|
|
|
}
|
|
|
|
lrunning = lrunning / latencies.length;
|
|
|
|
|
|
|
|
if (latency < lmin) {
|
|
|
|
lmin = latency;
|
|
|
|
}
|
|
|
|
if (latency > lmax) {
|
|
|
|
lmax = latency;
|
|
|
|
}
|
|
|
|
|
|
|
|
showStats();
|
|
|
|
//console.log("<< check_respond");
|
|
|
|
}
|
|
|
|
|
|
|
|
function sendMsg() {
|
|
|
|
var arr = [];
|
2011-01-24 01:30:51 +00:00
|
|
|
if (! ws.flush() ) {
|
|
|
|
message("WebSocket not ready, backing off");
|
|
|
|
actualSendDelay = actualSendDelay * 2;
|
|
|
|
send_ref = setTimeout(sendMsg, actualSendDelay);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
// Scale the delay down to the requested minimum
|
|
|
|
if (actualSendDelay > sendDelay) {
|
|
|
|
message("WebSocket ready, increasing presure");
|
|
|
|
actualSendDelay = Math.max(actualSendDelay / 2, sendDelay);
|
|
|
|
}
|
2011-01-19 21:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
timestamp = (new Date()).getTime();
|
2011-05-02 04:17:04 +01:00
|
|
|
arr.pushStr("^" + send_seq + ":" + timestamp + ":" + payload + "$");
|
2011-01-19 21:25:44 +00:00
|
|
|
send_seq ++;
|
2011-01-24 01:30:51 +00:00
|
|
|
ws.send(arr);
|
2011-01-19 21:25:44 +00:00
|
|
|
sent++;
|
|
|
|
|
|
|
|
showStats();
|
2011-01-24 01:30:51 +00:00
|
|
|
send_ref = setTimeout(sendMsg, actualSendDelay);
|
2011-01-19 21:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function showStats() {
|
|
|
|
$D('sent').innerHTML = sent;
|
|
|
|
$D('received').innerHTML = received;
|
|
|
|
$D('laverage').innerHTML = laverage.toFixed(2);
|
|
|
|
$D('lrunning').innerHTML = lrunning.toFixed(2);
|
|
|
|
$D('lmin').innerHTML = lmin.toFixed(2);
|
|
|
|
$D('lmax').innerHTML = lmax.toFixed(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
function init_ws() {
|
|
|
|
console.log(">> init_ws");
|
|
|
|
var scheme = "ws://";
|
|
|
|
if ($D('encrypt').checked) {
|
|
|
|
scheme = "wss://";
|
|
|
|
}
|
|
|
|
var uri = scheme + host + ":" + port;
|
|
|
|
console.log("connecting to " + uri);
|
2011-01-24 01:30:51 +00:00
|
|
|
ws = new Websock();
|
|
|
|
ws.maxBufferedAmount = 5000;
|
|
|
|
ws.open(uri);
|
|
|
|
|
2011-05-02 04:17:04 +01:00
|
|
|
ws.on('message', function() {
|
2011-01-24 01:30:51 +00:00
|
|
|
recvMsg();
|
|
|
|
});
|
2011-05-02 04:17:04 +01:00
|
|
|
ws.on('open', function() {
|
2011-01-24 01:30:51 +00:00
|
|
|
send_ref = setTimeout(sendMsg, sendDelay);
|
|
|
|
});
|
|
|
|
ws.on('close', function(e) {
|
|
|
|
disconnect();
|
|
|
|
});
|
|
|
|
ws.on('error', function(e) {
|
|
|
|
message("Websock error: " + e);
|
|
|
|
disconnect();
|
|
|
|
});
|
2011-01-19 21:25:44 +00:00
|
|
|
|
|
|
|
console.log("<< init_ws");
|
|
|
|
}
|
|
|
|
|
|
|
|
function connect() {
|
|
|
|
console.log(">> connect");
|
|
|
|
host = $D('host').value;
|
|
|
|
port = $D('port').value;
|
|
|
|
payload_size = parseInt($D('payload_size').value, 10);
|
|
|
|
sendDelay = parseInt($D('sendDelay').value, 10);
|
|
|
|
|
|
|
|
if ((!host) || (!port)) {
|
|
|
|
console.log("must set host and port");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ws) {
|
|
|
|
ws.close();
|
|
|
|
}
|
|
|
|
init_ws();
|
|
|
|
|
|
|
|
// Populate payload data
|
|
|
|
var numlist = []
|
|
|
|
for (var i=0; i < payload_size; i++) {
|
|
|
|
numlist.push( Math.floor(Math.random()*10) );
|
|
|
|
}
|
|
|
|
payload = numlist.join('');
|
|
|
|
|
|
|
|
// Initialize stats
|
|
|
|
sent = 0;
|
|
|
|
received = 0;
|
|
|
|
latencies = [];
|
|
|
|
ltotal = 0;
|
|
|
|
laverage = 0;
|
|
|
|
lrunning = 0;
|
|
|
|
lmin = 999999999;
|
|
|
|
lmax = 0;
|
2011-01-24 01:30:51 +00:00
|
|
|
actualSendDelay = sendDelay;
|
2011-01-19 21:25:44 +00:00
|
|
|
|
|
|
|
$D('connectButton').value = "Stop";
|
|
|
|
$D('connectButton').onclick = disconnect;
|
|
|
|
console.log("<< connect");
|
|
|
|
}
|
|
|
|
|
|
|
|
function disconnect() {
|
|
|
|
console.log(">> disconnect");
|
|
|
|
if (ws) {
|
|
|
|
ws.close();
|
|
|
|
}
|
|
|
|
|
2011-01-24 01:30:51 +00:00
|
|
|
if (send_ref) {
|
|
|
|
clearInterval(send_ref);
|
|
|
|
send_ref = null;
|
|
|
|
}
|
2011-01-19 21:25:44 +00:00
|
|
|
showStats(); // Final numbers
|
|
|
|
recv_seq = 0;
|
|
|
|
send_seq = 0;
|
|
|
|
|
|
|
|
$D('connectButton').value = "Start";
|
|
|
|
$D('connectButton').onclick = connect;
|
|
|
|
console.log("<< disconnect");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
window.onload = function() {
|
|
|
|
console.log("onload");
|
2011-01-24 01:30:51 +00:00
|
|
|
if (Websock_native) {
|
2011-01-19 21:25:44 +00:00
|
|
|
message("Using native WebSockets");
|
|
|
|
} else {
|
|
|
|
message("initializing web-socket-js flash bridge");
|
|
|
|
}
|
|
|
|
var url = document.location.href;
|
|
|
|
$D('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
|
|
|
$D('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
|
|
|
$D('payload_size').value = payload_size;
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
</html>
|