262 lines
8.4 KiB
HTML
262 lines
8.4 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<title>WebSockets Latency Test</title>
|
|
</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>
|
|
|
|
var host = null, port = null, sendDelay = 0,
|
|
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 = document.getElementById('messages');
|
|
msg_cnt++;
|
|
cell.innerHTML += msg_cnt + ": " + str + "\n";
|
|
cell.scrollTop = cell.scrollHeight;
|
|
}
|
|
|
|
|
|
function add (x,y) {
|
|
return parseInt(x,10)+parseInt(y,10);
|
|
}
|
|
|
|
function recvMsg(data) {
|
|
//console.log(">> check_respond");
|
|
var i, now, arr, first, last, arr, latency;
|
|
|
|
now = (new Date()).getTime(); // Early as possible
|
|
|
|
arr = new Uint8Array(data);
|
|
first = String.fromCharCode(arr[0]);
|
|
last = String.fromCharCode(arr[arr.length-1]);
|
|
|
|
if (first != "^") {
|
|
message("Error: packet missing start char '^'");
|
|
disconnect();
|
|
return;
|
|
}
|
|
if (last != "$") {
|
|
message("Error: packet missing end char '$'");
|
|
disconnect();
|
|
return;
|
|
}
|
|
text = ''
|
|
for (var i = 1; i < arr.length-1; i++) {
|
|
text += String.fromCharCode(arr[i]);
|
|
}
|
|
arr = text.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 = [];
|
|
timestamp = (new Date()).getTime();
|
|
arr.pushStr("^" + send_seq + ":" + timestamp + ":" + payload + "$");
|
|
send_seq ++;
|
|
ws.send(new Uint8Array(arr));
|
|
sent++;
|
|
|
|
showStats();
|
|
send_ref = setTimeout(sendMsg, sendDelay);
|
|
}
|
|
|
|
function showStats() {
|
|
document.getElementById('sent').innerHTML = sent;
|
|
document.getElementById('received').innerHTML = received;
|
|
document.getElementById('laverage').innerHTML = laverage.toFixed(2);
|
|
document.getElementById('lrunning').innerHTML = lrunning.toFixed(2);
|
|
document.getElementById('lmin').innerHTML = lmin.toFixed(2);
|
|
document.getElementById('lmax').innerHTML = lmax.toFixed(2);
|
|
}
|
|
|
|
function init_ws() {
|
|
console.log(">> init_ws");
|
|
var scheme = "ws://";
|
|
if (document.getElementById('encrypt').checked) {
|
|
scheme = "wss://";
|
|
}
|
|
var uri = scheme + host + ":" + port;
|
|
console.log("connecting to " + uri);
|
|
ws = new WebSocket(uri);
|
|
ws.binaryType = 'arraybuffer';
|
|
|
|
ws.addEventListener('message', function(e) {
|
|
recvMsg(e.data);
|
|
});
|
|
ws.addEventListener('open', function() {
|
|
send_ref = setTimeout(sendMsg, sendDelay);
|
|
});
|
|
ws.addEventListener('close', function(e) {
|
|
disconnect();
|
|
});
|
|
ws.addEventListener('error', function(e) {
|
|
message("Websock error: " + e);
|
|
disconnect();
|
|
});
|
|
|
|
console.log("<< init_ws");
|
|
}
|
|
|
|
function connect() {
|
|
console.log(">> connect");
|
|
host = document.getElementById('host').value;
|
|
port = document.getElementById('port').value;
|
|
payload_size = parseInt(document.getElementById('payload_size').value, 10);
|
|
sendDelay = parseInt(document.getElementById('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;
|
|
|
|
document.getElementById('connectButton').value = "Stop";
|
|
document.getElementById('connectButton').onclick = disconnect;
|
|
console.log("<< connect");
|
|
}
|
|
|
|
function disconnect() {
|
|
console.log(">> disconnect");
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
if (send_ref) {
|
|
clearInterval(send_ref);
|
|
send_ref = null;
|
|
}
|
|
showStats(); // Final numbers
|
|
recv_seq = 0;
|
|
send_seq = 0;
|
|
|
|
document.getElementById('connectButton').value = "Start";
|
|
document.getElementById('connectButton').onclick = connect;
|
|
console.log("<< disconnect");
|
|
}
|
|
|
|
|
|
window.onload = function() {
|
|
console.log("onload");
|
|
var url = document.location.href;
|
|
document.getElementById('host').value = (url.match(/host=([^&#]*)/) || ['',window.location.hostname])[1];
|
|
document.getElementById('port').value = (url.match(/port=([^&#]*)/) || ['',window.location.port])[1];
|
|
document.getElementById('payload_size').value = payload_size;
|
|
}
|
|
</script>
|
|
|
|
</html>
|