[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250]
<!DOCTYPE html> <html> <head> <!-- Copyright (C) 2010-2013 Mark G.Daniel This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. http://www.gnu.org/licenses/gpl.txt --> <title>WebSocket Scripting - Mouse Demonstration</title> <style type="text/css"> body { font-family: sans-serif, arial, helvetica; font-size:11pt; } .demo { font-size:130%; font-weight:bold; text-decoration:underline; text-align:center; } .application th { text-align:right; vertical-align:top; } .clientab th { padding:0.2em 0 0.2em 1em; text-align:right; } .clientab td { padding:0.2em 0 0.2em 1em; text-align:right; font-family:monospace; } .clients { width:99%; margin:1em; background-color:whiteSmoke; } .revealhide { font-weight:bold; } .documentation { display:none; padding:0 2em 0 2em; } </style> <script language="JavaScript"> function testWebSocketSupport() { return ('WebSocket' in window && window.WebSocket.CLOSING === 2); } function reportWebSocketSupport() { var level = testWebSocketSupport(); if (level != 1) document.getElementById("nowebsocket").innerHTML = '<span style="background-color:#ff0000;padding:1px;font-size:120%;">\ This browser does not support WebSocket!\ </span><br /><i>' + navigator.userAgent + '</i>'; } if (window.addEventListener) window.addEventListener("load", reportWebSocketSupport, false); else if (window.attachEvent) window.attachEvent("onload", reportWebSocketSupport); </script> </head> <body onmousemove="mouseMove(event)" on__mouseout="mouseMove(event)"> <div id="dbug"></div> <table class="application" cellpadding="5" cellspacing="5" border="0"> <tr><td colspan="3" class="demo">WebSocket Scripting — Mouse Demonstration</td></tr> <tr><td id="OnNext" colspan="3" style="text-align:center;"></td></tr> <tr><td id="nowebsocket" colspan="3" style="text-align:center;"></td></tr> <tr> <th align="left">Clients:</th> <td id="clients" class="clients" onMouseOver="webSocketOpen()">[closed]</td> </tr> </table> <br> <div class="revealhide">Description <tt>[<a name="descrip" href="javascript:revealHide('descrip')">+</a>]</tt></div> <div name="descrip" class="documentation"> <p>This example illustrates the fine granularity of the <b>asynchronous, bi-directional</b> network channel provided by a WebSocket.</p> <p>To begin, move the mouse over the [closed] indicator. A WebSocket connection will be established with the server-side application (script). This application <b>handles multiple, concurrent clients</b>. Your connection has the <i>host:port</i> underlined. The mouse position of all connected clients is displayed to each client. With each mouse movement on the page the cursor position is sent to the application where it updates that client's status. With each client update <b>all connected clients</b> have the revised mouse position display updated. To help manage potential bandwidth consumption the update rate is explicitly limited at both client and server.</p> <p>If left unused the WebSocket is disconnected by the server-side application and can be restarted by moving the mouse over the [disconnected] indicator. <p>This demonstration is JavaScript-driven at the browser end</p> <p style="margin-left:2em;"><tt>WASD_ROOT:[SRC.WEBSOCKET]<a target="_blank" href="ws_mouse.html?httpd=content&type=text/plain">WS_MOUSE.HTML</a></tt></p> <p>and uses a WebSocket protocol application (script) at the WASD server end</p> <p style="margin-left:2em;"><tt>WASD_ROOT:[SRC.WEBSOCKET]<a target="_blank" href="ws_mouse.c">WS_MOUSE.C</a></tt></p> <p>All of these interactions can be observed using the WASD WATCH facility; [x]CGI, [x]DCL and [x]Network Data items.</p> </div> <div class="revealhide">Configuration <tt>[<a name="config" href="javascript:revealHide('config')">+</a>]</tt></div> <div name="config" class="documentation"> <p>The script is a native WebSocket protocol application and so the executable should only need placing in the script directory.</p> <p> To effectively display multiple clients the script must rely on there being only a single instance of it executing (a particular issue when employing multiple WASD instances). Generally the server will only need to instantiate a single WS_MOUSE script to handle multiple clients, however there is a small window when the client request is being accepted by the script where it is unavailable. <p> Suppress host name lookup by defining the logical name WS_MOUSE_NO_LOOKUP. </div> <script language="JavaScript"> if (window.location.protocol == "http:") var URL = "ws://"; else var URL = "wss://"; URL += window.location.host + "/cgiplus-bin/ws_mouse" var ws = null; var meIdent = null; var sendMsg = null; var sendTimer = null; var updateRate = 200; var webSocketConnected = false; var webSocketNotSupported = false; var clientsObj = document.getElementById("clients"); var dbugObj = document.getElementById("dbug"); function dbugOut (text) { dbugObj.innerHTML = text; } function mouseMove (event) { if (!webSocketConnected) return; if (event.type == "mousemove") sendMsg = event.clientX + "," + event.clientY; else sendMsg = ""; if (!updateRate) sendMove (); else if (!sendTimer) sendTimer = setTimeout ("sendMove()",updateRate); } function sendMove () { if (!webSocketConnected) return; if (!sendMsg) return; if (ws) ws.send(sendMsg); sendMsg = sendTimer = 0; } function displayData (data) { // data comes one line per client as bar-separated items // turn these into a an HTML table formatting the client data var table = "<table class=\"clientab\">"; table += "<tr><th></th><th>Connect</th><th>Client</th>"; table += "<th>Update</th><th style=\"width:6em;\">Mouse</th></tr>\n"; data = data.split("\n"); var cnt = 0; while (cnt < data.length) { var one = data[cnt].split("|"); if (one.length == 6) { table += "<tr>"; table += "<th>" + one[1] + "</th>"; table += "<td>" + one[2] + "</td>"; if (one[0] == meIdent) table += "<td style=\"text-decoration:underline;\">"; else table += "<td>"; table += one[3] + "</td>"; table += "<td>" + one[4] + "</td>"; table += "<td>" + one[5] + "</td>"; table += "</tr>"; } cnt++; } table += "</table>"; clientsObj.innerHTML = table; } function webSocketOpen () { if ("WebSocket" in window) { if (ws) return false; ws = new WebSocket(URL); ws.onopen = function(evt) { clientsObj.innerHTML = "[open]"; webSocketConnected = true; }; ws.onclose = function(evt) { clientsObj.innerHTML = "[disconnected]"; ws = null; webSocketConnected = false; }; ws.onmessage = function (evt) { if (evt.data == "update=max") updateRate = 0; else if (evt.data.substr(0,4) == "you=") meIdent = evt.data.substr(4); else if (evt.data.substr(0,6) == "OnNext") document.getElementById("OnNext").innerHTML = "WsLibOnNextRequest()"; else displayData (evt.data); }; updateRate = 200; clientsObj.innerHTML = "[connecting...]"; } else { if (!webSocketNotSupported) { clientsObj.innerHTML = "WebSocket not supported!"; webSocketNotSupported = true; } } return false; } function revealHide (name) { var nameAry = document.getElementsByName(name); var ancObj = nameAry[0]; var divObj = nameAry[1]; if (divObj.style.display == "block") { ancObj.innerHTML = "+"; divObj.style.display = "none"; } else { ancObj.innerHTML = "-"; divObj.style.display = "block"; } } </script> </body> </html>