latency.html 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <html>
  2. <head>
  3. <title>WebSockets Latency Test</title>
  4. </head>
  5. <body>
  6. Host: <input id='host' style='width:100'>&nbsp;
  7. Port: <input id='port' style='width:50'>&nbsp;
  8. Encrypt: <input id='encrypt' type='checkbox'>
  9. <br>
  10. Payload Size: <input id='payload_size' style='width:50'>&nbsp;
  11. Send Delay (ms): <input id='sendDelay' style='width:50' value="10">&nbsp;
  12. <input id='connectButton' type='button' value='Start' style='width:100px'
  13. onclick="connect();">&nbsp;
  14. <br><br>
  15. <table border=1>
  16. <tr>
  17. <th align="right">Packets sent:</th>
  18. <td align="right"><div id='sent'></div></td>
  19. </tr><tr>
  20. <th align="right">Packets Received:</th>
  21. <td align="right"><div id='received'></div></td>
  22. </tr><tr>
  23. <th align="right">Average Latency:</th>
  24. <td align="right"><div id='laverage'></div></td>
  25. </tr><tr>
  26. <th align="right">40 Frame Running Average Latency:</th>
  27. <td align="right"><div id='lrunning'></div></td>
  28. </tr><tr>
  29. <th align="right">Minimum Latency:</th>
  30. <td align="right"><div id='lmin'></div></td>
  31. </tr><tr>
  32. <th align="right">Maximum Latency:</th>
  33. <td align="right"><div id='lmax'></div></td>
  34. </tr>
  35. </table>
  36. <br>
  37. Messages:<br>
  38. <textarea id="messages" style="font-size: 9;" cols=80 rows=10></textarea>
  39. </body>
  40. <script>
  41. var host = null, port = null, sendDelay = 0,
  42. ws = null, send_ref = null,
  43. sent, received, latencies, ltotal, laverage, lrunning, lmin, lmax,
  44. run_length = 40,
  45. payload_size = 2000, payload,
  46. msg_cnt = 0, recv_seq = 0, send_seq = 0;
  47. Array.prototype.pushStr = function (str) {
  48. var n = str.length;
  49. for (var i=0; i < n; i++) {
  50. this.push(str.charCodeAt(i));
  51. }
  52. }
  53. function message(str) {
  54. console.log(str);
  55. cell = document.getElementById('messages');
  56. msg_cnt++;
  57. cell.innerHTML += msg_cnt + ": " + str + "\n";
  58. cell.scrollTop = cell.scrollHeight;
  59. }
  60. function add (x,y) {
  61. return parseInt(x,10)+parseInt(y,10);
  62. }
  63. function recvMsg(data) {
  64. //console.log(">> check_respond");
  65. var i, now, arr, first, last, arr, latency;
  66. now = (new Date()).getTime(); // Early as possible
  67. arr = new Uint8Array(data);
  68. first = String.fromCharCode(arr[0]);
  69. last = String.fromCharCode(arr[arr.length-1]);
  70. if (first != "^") {
  71. message("Error: packet missing start char '^'");
  72. disconnect();
  73. return;
  74. }
  75. if (last != "$") {
  76. message("Error: packet missing end char '$'");
  77. disconnect();
  78. return;
  79. }
  80. text = ''
  81. for (var i = 1; i < arr.length-1; i++) {
  82. text += String.fromCharCode(arr[i]);
  83. }
  84. arr = text.split(':');
  85. seq = arr[0];
  86. timestamp = parseInt(arr[1],10);
  87. rpayload = arr[2];
  88. if (seq != recv_seq) {
  89. message("Error: expected seq " + recv_seq + " but got " + seq);
  90. disconnect();
  91. return;
  92. }
  93. recv_seq++;
  94. if (payload !== rpayload) {
  95. message("Payload corrupt");
  96. disconnect();
  97. return;
  98. }
  99. received++;
  100. latency = now - timestamp;
  101. latencies.push(latency);
  102. if (latencies.length > run_length) {
  103. latencies.shift();
  104. }
  105. ltotal += latency;
  106. laverage = ltotal / received;
  107. lrunning = 0;
  108. for (var i=0; i < latencies.length; i++) {
  109. lrunning += latencies[i];
  110. }
  111. lrunning = lrunning / latencies.length;
  112. if (latency < lmin) {
  113. lmin = latency;
  114. }
  115. if (latency > lmax) {
  116. lmax = latency;
  117. }
  118. showStats();
  119. //console.log("<< check_respond");
  120. }
  121. function sendMsg() {
  122. var arr = [];
  123. timestamp = (new Date()).getTime();
  124. arr.pushStr("^" + send_seq + ":" + timestamp + ":" + payload + "$");
  125. send_seq ++;
  126. ws.send(new Uint8Array(arr));
  127. sent++;
  128. showStats();
  129. send_ref = setTimeout(sendMsg, sendDelay);
  130. }
  131. function showStats() {
  132. document.getElementById('sent').innerHTML = sent;
  133. document.getElementById('received').innerHTML = received;
  134. document.getElementById('laverage').innerHTML = laverage.toFixed(2);
  135. document.getElementById('lrunning').innerHTML = lrunning.toFixed(2);
  136. document.getElementById('lmin').innerHTML = lmin.toFixed(2);
  137. document.getElementById('lmax').innerHTML = lmax.toFixed(2);
  138. }
  139. function init_ws() {
  140. console.log(">> init_ws");
  141. var scheme = "ws://";
  142. if (document.getElementById('encrypt').checked) {
  143. scheme = "wss://";
  144. }
  145. var uri = scheme + host + ":" + port;
  146. console.log("connecting to " + uri);
  147. ws = new WebSocket(uri);
  148. ws.binaryType = 'arraybuffer';
  149. ws.addEventListener('message', function(e) {
  150. recvMsg(e.data);
  151. });
  152. ws.addEventListener('open', function() {
  153. send_ref = setTimeout(sendMsg, sendDelay);
  154. });
  155. ws.addEventListener('close', function(e) {
  156. disconnect();
  157. });
  158. ws.addEventListener('error', function(e) {
  159. message("Websock error: " + e);
  160. disconnect();
  161. });
  162. console.log("<< init_ws");
  163. }
  164. function connect() {
  165. console.log(">> connect");
  166. host = document.getElementById('host').value;
  167. port = document.getElementById('port').value;
  168. payload_size = parseInt(document.getElementById('payload_size').value, 10);
  169. sendDelay = parseInt(document.getElementById('sendDelay').value, 10);
  170. if ((!host) || (!port)) {
  171. console.log("must set host and port");
  172. return;
  173. }
  174. if (ws) {
  175. ws.close();
  176. }
  177. init_ws();
  178. // Populate payload data
  179. var numlist = []
  180. for (var i=0; i < payload_size; i++) {
  181. numlist.push( Math.floor(Math.random()*10) );
  182. }
  183. payload = numlist.join('');
  184. // Initialize stats
  185. sent = 0;
  186. received = 0;
  187. latencies = [];
  188. ltotal = 0;
  189. laverage = 0;
  190. lrunning = 0;
  191. lmin = 999999999;
  192. lmax = 0;
  193. document.getElementById('connectButton').value = "Stop";
  194. document.getElementById('connectButton').onclick = disconnect;
  195. console.log("<< connect");
  196. }
  197. function disconnect() {
  198. console.log(">> disconnect");
  199. if (ws) {
  200. ws.close();
  201. }
  202. if (send_ref) {
  203. clearInterval(send_ref);
  204. send_ref = null;
  205. }
  206. showStats(); // Final numbers
  207. recv_seq = 0;
  208. send_seq = 0;
  209. document.getElementById('connectButton').value = "Start";
  210. document.getElementById('connectButton').onclick = connect;
  211. console.log("<< disconnect");
  212. }
  213. window.onload = function() {
  214. console.log("onload");
  215. var url = document.location.href;
  216. document.getElementById('host').value = (url.match(/host=([^&#]*)/) || ['',window.location.hostname])[1];
  217. document.getElementById('port').value = (url.match(/port=([^&#]*)/) || ['',window.location.port])[1];
  218. document.getElementById('payload_size').value = payload_size;
  219. }
  220. </script>
  221. </html>