4
<title>WebSockets Latency Test</title>
5
<script src="include/base64.js"></script>
6
<script src="include/util.js"></script>
7
<script src="include/webutil.js"></script>
8
<script src="include/websock.js"></script>
9
<!-- Uncomment to activate firebug lite -->
11
<script type='text/javascript'
12
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
20
Host: <input id='host' style='width:100'>
21
Port: <input id='port' style='width:50'>
22
Encrypt: <input id='encrypt' type='checkbox'>
24
Payload Size: <input id='payload_size' style='width:50'>
25
Send Delay (ms): <input id='sendDelay' style='width:50' value="10">
26
<input id='connectButton' type='button' value='Start' style='width:100px'
27
onclick="connect();">
32
<th align="right">Packets sent:</th>
33
<td align="right"><div id='sent'></div></td>
35
<th align="right">Packets Received:</th>
36
<td align="right"><div id='received'></div></td>
38
<th align="right">Average Latency:</th>
39
<td align="right"><div id='laverage'></div></td>
41
<th align="right">40 Frame Running Average Latency:</th>
42
<td align="right"><div id='lrunning'></div></td>
44
<th align="right">Minimum Latency:</th>
45
<td align="right"><div id='lmin'></div></td>
47
<th align="right">Maximum Latency:</th>
48
<td align="right"><div id='lmax'></div></td>
54
<textarea id="messages" style="font-size: 9;" cols=80 rows=10></textarea>
60
var host = null, port = null, sendDelay = 0, actualSendDelay,
61
ws = null, send_ref = null,
62
sent, received, latencies, ltotal, laverage, lrunning, lmin, lmax,
64
payload_size = 2000, payload,
65
msg_cnt = 0, recv_seq = 0, send_seq = 0;
67
Array.prototype.pushStr = function (str) {
69
for (var i=0; i < n; i++) {
70
this.push(str.charCodeAt(i));
75
function message(str) {
77
cell = $D('messages');
79
cell.innerHTML += msg_cnt + ": " + str + "\n";
80
cell.scrollTop = cell.scrollHeight;
85
return parseInt(x,10)+parseInt(y,10);
88
function recvMsg(data) {
89
//console.log(">> check_respond");
90
var i, now, arr, first, last, arr, latency;
92
now = (new Date()).getTime(); // Early as possible
94
arr = ws.rQshiftBytes(ws.rQlen());
95
first = String.fromCharCode(arr.shift());
96
last = String.fromCharCode(arr.pop());
99
message("Error: packet missing start char '^'");
104
message("Error: packet missing end char '$'");
108
arr = arr.map(function(num) {
109
return String.fromCharCode(num);
110
} ).join('').split(':');
112
timestamp = parseInt(arr[1],10);
115
if (seq != recv_seq) {
116
message("Error: expected seq " + recv_seq + " but got " + seq);
121
if (payload !== rpayload) {
122
message("Payload corrupt");
129
latency = now - timestamp;
130
latencies.push(latency);
131
if (latencies.length > run_length) {
135
laverage = ltotal / received;
137
for (var i=0; i < latencies.length; i++) {
138
lrunning += latencies[i];
140
lrunning = lrunning / latencies.length;
142
if (latency < lmin) {
145
if (latency > lmax) {
150
//console.log("<< check_respond");
156
message("WebSocket not ready, backing off");
157
actualSendDelay = actualSendDelay * 2;
158
send_ref = setTimeout(sendMsg, actualSendDelay);
161
// Scale the delay down to the requested minimum
162
if (actualSendDelay > sendDelay) {
163
message("WebSocket ready, increasing presure");
164
actualSendDelay = Math.max(actualSendDelay / 2, sendDelay);
168
timestamp = (new Date()).getTime();
169
arr.pushStr("^" + send_seq + ":" + timestamp + ":" + payload + "$");
175
send_ref = setTimeout(sendMsg, actualSendDelay);
178
function showStats() {
179
$D('sent').innerHTML = sent;
180
$D('received').innerHTML = received;
181
$D('laverage').innerHTML = laverage.toFixed(2);
182
$D('lrunning').innerHTML = lrunning.toFixed(2);
183
$D('lmin').innerHTML = lmin.toFixed(2);
184
$D('lmax').innerHTML = lmax.toFixed(2);
188
console.log(">> init_ws");
189
var scheme = "ws://";
190
if ($D('encrypt').checked) {
193
var uri = scheme + host + ":" + port;
194
console.log("connecting to " + uri);
196
ws.maxBufferedAmount = 5000;
199
ws.on('message', function() {
202
ws.on('open', function() {
203
send_ref = setTimeout(sendMsg, sendDelay);
205
ws.on('close', function(e) {
208
ws.on('error', function(e) {
209
message("Websock error: " + e);
213
console.log("<< init_ws");
217
console.log(">> connect");
218
host = $D('host').value;
219
port = $D('port').value;
220
payload_size = parseInt($D('payload_size').value, 10);
221
sendDelay = parseInt($D('sendDelay').value, 10);
223
if ((!host) || (!port)) {
224
console.log("must set host and port");
233
// Populate payload data
235
for (var i=0; i < payload_size; i++) {
236
numlist.push( Math.floor(Math.random()*10) );
238
payload = numlist.join('');
249
actualSendDelay = sendDelay;
251
$D('connectButton').value = "Stop";
252
$D('connectButton').onclick = disconnect;
253
console.log("<< connect");
256
function disconnect() {
257
console.log(">> disconnect");
263
clearInterval(send_ref);
266
showStats(); // Final numbers
270
$D('connectButton').value = "Start";
271
$D('connectButton').onclick = connect;
272
console.log("<< disconnect");
276
window.onload = function() {
277
console.log("onload");
278
if (Websock_native) {
279
message("Using native WebSockets");
281
message("initializing web-socket-js flash bridge");
283
var url = document.location.href;
284
$D('host').value = (url.match(/host=([^&#]*)/) || ['',window.location.hostname])[1];
285
$D('port').value = (url.match(/port=([^&#]*)/) || ['',window.location.port])[1];
286
$D('payload_size').value = payload_size;