Step
The following procedures let you create a broadcast setup:
|
Step |
Procedure |
Description |
|---|---|---|
|
1 |
Define communication channels in the Application.cfc |
Client can subscribe or publish to a pre-defined set of channels. To listen to the channel, first register it at the application level. |
|
2 |
Create WebSocket object using the cfwebsocket tag in your CFM template |
Creates WebSocket connection with all required properties automatically, and wraps it in a JavaScript object that can invoke various JavaScript methods. The tag internally identifies the IP address and port of the server. |
|
3 |
Implement the business logic using the JavaScript functions provided by the WebSocket object |
On runtime, you can make use of the supported JavaScript functions for example, subscribe or publish to achieve your business goals. |
Specify the following settings in the Application.cfc to define the communication channel:
{
this.name="testapp";
this.wschannels=[{name = channelName,cfclistener= channel_listener_CFC}];
}
Specify the channel name.
Though you can use any number of sub-channels, you do not specify them. They are dynamically created.
The new ColdFusion tag {{cfwebsocket }}lets you create the WebSocket object in your CFM template. The tag creates a reference to the WebSocket JavaScript object at the client-side.
name="websocketName" onMessage="JavaScript function name" onOpen="JavaScript function name" onClose="JavaScript function name" onError="JavaScript function name" useCfAuth=true|false subscribeTo="channel_list">
Attribute
|
Attribute |
Req/Opt |
Descriptions |
|---|---|---|
|
name |
Required |
The name of the WebSocket object. This is the reference to the JavaScript objects that are used to call WebSocket JavaScript functions. |
|
onMessage |
Required |
The JavaScript function that is called when the WebSocket receives a message from the server. The function requires one argument. |
|
onOpen |
Optional |
The JavaScript function that is called when the WebSocket establishes a connection.The function does not require any arguments. |
|
onClose |
Optional |
The JavaScript function that is called when the WebSocket closes a connection.The function does not require any arguments. |
|
onError |
Optional |
The JavaScript function that is called if there is an error while performing an action over the WebSocket connection. The function requires one argument. |
|
usecfAuth |
Optional |
If set to true (default), authentication is not required for WebSocket connection (provided they have already logged in to the application). This is the default value.If false, to authenticate, you have to use the javaScript function authenticate. |
|
subscribeTo |
Optional |
Comma-separated list of channels/subchannels to subscribe to. You can specify any or all channels set in the Application.cfc. |
By specifying the attribute name, for example, mycfwebsocketobject (as in the following example), you create a JavaScript object. The JavaScript object can be used to call various JavaScript functions which you use for the WebSocket communication.
In the following example,
In the Index.cfm, you specify the channels to which the user can automatically subscribe to (using the attribute subscribeTo) and also define the message handler.
Application.cfc
{
this.name="websocketsampleapp1";
this.wschannels=[{name="stocks"}];
}
Index.cfm
<script type="text/javascript">
/* mymessangehandler function recieves all messages that comes via WebSocket. This function requires one argument.
*/
function mymessagehandler(messageObject)
{
//JavaScript messageobject is converted to a string.
var message = ColdFusion.JSON.encode(messageObject);
var txt=document.getElementById("myDiv");
txt.innerHTML +=message +"<br>";
}
</script>
<cfwebsocket name="mycfwebsocketobject" onmessage="mymessagehandler" subscribeto="stocks" >
<cfdiv id="myDiv"></cfdiv>
The code creates a JavaScript WebSocket object named mycfwebsocketobject. If the server sends a message, it calls mymessagehandler function.Since you have specified subscribeTo in the cfwebsocket tag, the WebSocket object automatically subscribes you to the channel stocks.
After you create a JavaScript WebSocket object using the cfwebsocket tag, you can use it to call the following JavaScript functions:
Function |
Description |
Syntax |
Parameters |
|
|---|---|---|---|---|
authenticate |
Authenticates the user to a specific channel. Returns true if the connection is open. |
authenticate(id, password)
mycfwebsocketobject.authenticate("Ben", "password") |
|
|
subscribe |
Lets the client subscribe to a specific channel. You can send additional information such as age of the user (in the form of custom_header JavaScript object) to the server. This information can be used to take a decision on whether to let the client subscribe or not. Returns true if the connection is open. |
subscribe(channel[, custom_header][, messageHandler])
mycfwebsocketobject.subscribe(channel) |
|
|
publish |
Publishes the message to the channel. If the message is not available use the function invokeAndPublish.Message can be passed in any JavaScript data type (such as array, string, int, or a key-value pair) as a JavaScript object.You can send additional information (in the form of custom_header). The information can be used to decide if to allow the client to publish, for example Only platinum members have rights to publish. Returns true if the connection is open. |
For example,
publish(channel, message [, custom_header]) mycfwebsocketobject.publish("stocks",msg) |
|
|
invokeAndPublish |
Invokes a specified method in a CFC file to generate the message that has to be published. Used in scnearios where you have raw data (that needs to be processed) to create a message. Returns true if the connection is open. |
For example,
invokeAndPublish(channel, cfcName, functionName [, argumentsArray] [, custom_header]) mycfwebsocketobject.invokeAndPublish(ch, "employee", "getEmployeeDetails", ["eid_1"]) |
|
|
getSubscriberCount |
Provides the number of subscribers for a specific channel. Returns true if the connection is open. |
For example,
getSubscriberCount(channel) mycfwebsocketobject.getSubscriberCount("stocks") |
|
|
getSubscriptions |
Provides all channels the client is subscribed to, as a JavaScript array. Returns true if the connection is open. |
getSubscription() |
Supports inline call back functionality to receive asynchronous response. |
|
openConnection |
Opens a WebSocket connection (if not already open). Returns undefined on successful completion. |
openConnection() |
|
|
isConnectionOpen |
Verifies whether the WebSocket connection is open. Returns true if the connection is open. |
isConnectionOpen() |
|
|
closeConnection |
Closes a WebSocket connection. Returns undefined on successful completion. The boolean value represents the status of the call only for openConnection and closeConnection. |
closeConnection() |
|
|
unsubscribe |
Unsubscribes a client from the specified channel. After the client unsubscribes, the messages in the channel are not published to the client. Returns true if the connection is open. |
For example,
unsubscribe(channel) mycfwebsocketobject.unsubscribe(channel) |
|
When you use these functions, a boolean value indicating the status of the call or connection is returned. But the result of the call is acknowledged at the message handler side. You can categorize the responses at the message handler using the request type token as shown in the following example: if (token.reqType =="getSubscriberCount). |
The following example illustrates how to use various JavaScript functions.Application.cfc
component
{
this.name="websocketsampleapp3";
this.wschannels=[{name="stocks"}];
}
Index.cfm
<script>
//messagehandler recieves all the messages from websocket
function mycbHandler( messageobj)
{
var message = ColdFusion.JSON.encode(messageobj);
var txt=document.getElementById("myDiv");
txt.innerHTML +=message +"<br>";
}
//openhandler is invoked when socket connection is
function openHandler()
{
var txt=document.getElementById("myDiv");
txt.innerHTML +="open Handler invoked <br>";
}
function subscribeMe()
{
var channelname = document.getElementById("channelname").value;
mywsobj.subscribe(channelname);
}
function getSubscribers()
{
var channelname = document.getElementById("channelname").value;
mywsobj.getSubscriberCount(channelname);
}
function unsubscribe_Me()
{
var channelname = document.getElementById("channelname").value;
mywsobj.unsubscribe(channelname);
}
function publishClient()
{
var channelname = document.getElementById("channelname").value;
var message = document.getElementById("msg").value;
mywsobj.publish(channelname,message);
}
function get_Subscriptions()
{
mywsobj.getSubscriptions();
}
function invokenpublish()
{
cfcname = document.getElementById("cfcname").value;
fnname = document.getElementById("fnname").value;
channelname = document.getElementById("channelname").value;
mywsobj.invokeAndPublish(channelname, cfcname, fnname);
}
function invokefn()
{
cfcname = document.getElementById("cfcname").value;
fnname = document.getElementById("fnname").value;
channelname = document.getElementById("channelname").value;
mywsobj.invoke(cfcname, fnname);
}
function opensocket()
{
var txt=document.getElementById("myDiv");
txt.innerHTML+="opening socket"+"<br >";
x=mywsobj.openConnection();
}
function stopsocket()
{
var txt=document.getElementById("myDiv");
txt.innerHTML+="closing socket"+"<br >";
x=mywsobj.closeConnection();
}
function checksocket()
{
var x=mywsobj.isConnectionOpen();
var txt=document.getElementById("myDiv");
txt.innerHTML+=x+"<br >";
}
</script>
<form name="f">
<!---Define JS websocket object name and messagehandler and openhandler --->
<cfwebsocket name="mywsobj" onMessage="mycbHandler" onOpen="openHandler"/>
<br> Subscribe to:
<input id="channelname" name="channelname" type="text" value="stocks" >
<input id="stocksSubscribe" type="button" value="stocksSubscribe" onclick="subscribeMe();">
<input id="unsubscribeMe" type="button" value="unsubscribeMe" onclick="unsubscribe_Me();">
<input id="getSubscribersCF" type="button" value="getSubscribersCF" onclick="getSubscribers();">
<input id="getSubscriptions" type="button" value="getSubscriptions" onclick="get_Subscriptions();">
<br>
Message :<input id="msg" type="text" >
<input id="publishMe" type="button" value="publishMe" onclick="publishClient();">
<br>
CFC Name: <input id="cfcname" name="cfcname" type="text" value="invokeandpublish" >
Function Name: <input id="fnname" name="fnname" type="text" value="publishall" >
<input id="invoke_publish" type="button" value="invoke_publish" onclick="invokenpublish();">
<input id="invoke" type="button" value="invoke" onclick="invokefn();">
<br>
<input id="stop" name ="Close" type="button" value ="stop" onclick="stopsocket()" >
<input id="open" name ="Open" type="button" value ="open" onclick="opensocket()" >
<input id="check" name ="Check" type="button" value="check" onclick="checksocket()" >
<br>
<div id="myDiv"></div>
</form>
invokeandpublish.cfc
component
{
public function publishall()
{
return "All Clients";
}
}
If the users subscribe to a parent channel, automatically they subscribe to all subchannels. If users subscribe to a child channel, they are not subscribed to its parent channel.
The following table elaborates the conditions.
The table shows four clients Client 1, Client 2, Client 3, and Client 4 subscribed to the following channels: Stocks, Stocks.Finance, Stocks.Banks, and Stocks.Finance.Adobe.
|
Client |
Channel subscribed to |
Receives messages when publishing to Stocks |
Receives messages when publishing to Stocks.Finance |
Receives messages when publishing to Stocks.Banks |
Receives messages when publishing to Stocks. Finance.Adobe |
|---|---|---|---|---|---|
|
Client 1 |
Stocks |
Yes |
Yes |
Yes |
Yes |
|
Client 2 |
Stocks.Finance |
No |
Yes |
No |
Yes |
|
Client 3 |
Stocks.Banks |
No |
No |
Yes |
No |
|
Client 4 |
Stocks.Finance.Adobe |
No |
No |
No |
Yes |
The following table explains the conditions on which you receive the subscriber list when you use the function getSubscribers.
Assume that there are four clients. Each client is subscribed to only one of the following channels (and no client is subscribed to the same channel): Stocks, Stocks.Finance, Stocks.Banks, and Stocks.Finance.Adobe.
|
Function getSubscribers called with the channel |
Returns the ID of clients subscribed to the following channels |
|---|---|
|
Stocks |
Stocks |
|
Stocks.Finance |
Stocks.Finance and Stocks |
|
Stocks.Banks |
Stocks.Banks and Stocks |
|
Stocks.Finance.Adobe |
Stocks.Finance.Adobe, Stocks.Finnance, and Stocks |
Channel listener is a set of functions that decide the folow of messages to a channel. When a WebSocket object's JavaScript function is called, in turn functions in the channel listener are called. For example, when you call the subscribe function, it calls the allowSubscribe function from the listener CFC.
The functions in the listener receive or provide information in the following three structs. You can use these three structs to add custom information.
The following table lists the WebSocket JavaScript functions and the corresponding function in the channel listener CFC:
WebSocket object JavaScript function |
Function(s) called in the channel listener CFC |
|---|---|
subscribe |
allowSubscribe |
unsubscribe |
afterUnsubscribe |
publish |
allowPublish |
invokeAndPublish |
allowPublish |
getSubscribers |
None |
getSubscriptions |
None |
invoke |
None |
openConnection |
None |
isConnectionOpen |
None |
closeConnection |
None |
The following table lists the functions in the listener file:
|
Function |
Descriptions |
Syntax |
Parameters |
|---|---|---|---|
|
allowSubscribe |
Invoked before subscribing to a channel/sub-channel. Used to check if the requested client can be allowed to subscribe to the given channel. If returns true, allows the requested client to subscribe.Properties defined in the object subscriberInfo can be used decide on authorization. |
allowSubscribe(subscriberInfo) |
|
|
allowPublish |
Called before publishing to a channel/sub-channel. Used to check whether the requested client can be allowed to publish to the given channel. Properties defined in the publisherInfo struct can be used to take the authorization decision. If returns true, allows the requested client to publish. |
allowPublish(publisherInfo) |
|
|
beforePublish |
Invoked before publishing the message on requested channel/sub-channel. Used to execute a business logic if required and to format messages. |
beforePublish(message, publisherInfo) |
|
|
canSendMessage |
Invoked before sending the message to a subscribed client.Used to decide whether the message should be sent to a specific client. Called for all clients subscribed to a channel separately. Properties defined in the object subscriberInfo and publisherInfo help you find client's interest in the message. |
canSendMessage(message, subscriberInfo, publisherInfo) |
|
|
beforeSendMessage |
Invoked before sending the message to a subscribed client. Can be used to format the message as per client requirement before sending. This function is executed for each client. |
beforeSendMessage(message, subscriberInfo) |
|
|
afterUnsubscribe |
Called after you unsubscribe from a channel/sub-channel. Used to clear the settings if necessary.. |
afterUnsubscribe (subscriberInfo) |
|
When you create a WebSocket object, you can define a message handler to manage responses from the server. The handler can manage messages from all the channels. Additionally, while subscribing to a channel, you can define channel-specific message handler.
Application.cfccomponent
{
this.name = "channelspecifichandlerexample";
this.wschannels = [{name="stocks"}, {name="news"}, {name="products"}];
}
index.cfm
<script type="text/javascript">
function stockhandler(stocksmessageobj){
//write appropriate logic here to handle data coming on stock channel
if (stocksmessageobj.data != null) {
var message = stocksmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Stock Handler: " + message + "<br />";
}
}
function newshandler(newsmessageobj){
//write appropriate logic here to handle data coming on news channel
if (newsmessageobj.data != null) {
var message = newsmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "News Handler: " + message + "<br />";
}
}
function productshandler(productsmessageobj){
//write appropriate logic here to handle data coming on products channel
if (productsmessageobj.data != null) {
var message = productsmessageobj.data;
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Product Handler: " + message + "<br />";
}
}
function subscribeMe(){
var channel = document.getElementById("channeloption").value;
switch (channel) {
case "stocks":
mysock.subscribe("stocks", {}, stockhandler);
break;
case "news":
mysock.subscribe("news", {}, newshandler);
break;
case "products":
mysock.subscribe("products", {}, productshandler);
break;
}
}
function mycbHandler(messageobj){
var message = ColdFusion.JSON.encode(messageobj);
var datadiv = document.getElementById("myDiv");
datadiv.innerHTML += "Message Handler : " + message + "<br />";
}
</script>
<cfwebsocket name="mysock" onmessage="mycbHandler"/>
<form>
<select id="channeloption">
<option>
stocks
</option>
<option>
news
</option>
<option>
products
</option>
</select>
<input id="subscribe" name="subscribe" value="Subscribe" type="button"
onclick="subscribeMe();">
</form>
<div id="myDiv">
</div>
PublishMessage.cfm
<cfscript>
if(isdefined("form.publish"))
WsPublish(#form.channel#, #form.message#);
</cfscript>
<cfform method="post">
<cfselect name="channel">
<option>
stocks
</option>
<option>
news
</option>
<option>
products
</option>
</cfselect>
Message:
<input id="message" name="message" type="text">
<cfinput id="publish" name="publish" value="publish" type="submit">
</cfform>
The following JavaScript functions subscribe, publish, invokeandpublish and the serverside function WSPublish let you pass custom information (for example age or status) in the form of key-value pairs.
You can use these custom data in the subscriberInfo in the channel listener.
In the following example,
Application.cfc
component
{
this.name = "customoptionexample";
this.wschannels = [{name="Testchannel", cfclistener="TestListener"}];
}
Index.cfm
<script type = "text/javascript">
function msgHandler(messageobj)
{
var ouputdiv=document.getElementById("myDiv");
var message = ColdFusion.JSON.encode(messageobj);
ouputdiv.innerHTML+=message +"<br >" +"<br>";
}
function subscribeMe()
{
var clientAge = document.getElementById("age").value;
TestSocket.subscribe("Testchannel", {age: clientAge}); }</script>
<cfwebsocket name="TestSocket" onMessage="msgHandler"/>
<br>
Age <input id="age" name="age" type="text">
<br>
<input id="stocksSubscribe" type="button" value="Subscribe" onclick="subscribeMe();">
<div id="myDiv"></div>
TestListener.cfc
component extends="CFIDE.websocket.ChannelListener"
{
public boolean function allowSubscribe(Struct subscriberInfo)
{
if(structKeyExists(subscriberInfo, "age"))
if((subscriberInfo.age gt 18)) {
return true;
}
else
{
return false;
}
else
return false;
}
}
The following example illustrates how you communicate bid value data.
Application.cfc
component
{
this.name = "customoptionexample1";
this.wschannels = [{name="bidchannel", cfclistener="bidListener"}];
boolean function onApplicationStart()
{
application.bidvalue = 1;
}
}
Index.cfm
<script type="text/javascript">
function msgHandler(messageobj){
if (messageobj.data != null) {
var ouputdiv = document.getElementById("myDiv");
var message = messageobj.data;
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
if (messageobj.code == -1 && messageobj.reqType == "publish") {
var ouputdiv = document.getElementById("myDiv");
var message = "Bid amount is less than current bid value";
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
}
function publishme(){
var bidvalue = document.getElementById("amount").value;
var clname = document.getElementById("name").value;
var message = "Bid placed by " + clname + " Amount " + bidvalue;
TestSocket.publish("bidchannel", message, {
value: bidvalue
});
}
</script>
<cfwebsocket name="TestSocket" onmessage="msgHandler" subscribeto="bidchannel"/><br>
Bid Amount:
<input id="amount" name="amount" type="text">
Name:
<input id="name" type="text">
<input id="publishmessage" type="button" value="Publish" onclick="publishme();">
<div id="myDiv">
</div>
bidListener.cfc
component extends="CFIDE.websocket.ChannelListener"{ public boolean function
allowPublish(Struct publisherInfo)
{
if(structKeyExists(publisherInfo, "value"))
if((publisherInfo.value gt application.bidvalue))
{
application.bidvalue = publisherInfo.value;
return true;
}
else
{ return false;
}
else
return false;
}
}
Selectors provide filtering logic when you subscribe to a channel or publish a message.
While subscribing to a channel, a selector is provided as part of the subscriber information struct. For example, a client is subscribed to a channel with a selector product eq abc. Only the messages that contain the publisher information product:abc are published to the subscriber.
Similarly, you can include a selector as part of the publisher information struct while publishing a message. The messages are published to only the subscribers who satisfy the criteria specified in the selector.
For a custom channel listener CFC, you cannot have the canSendMessage method (for the selector to work).
The following example shows how to subscribe to a channel with a selector:
Create a channel selectorchannel in the Application.cfc.
{
this.name = "websocketApp1";
this.wschannels = [{name="selectorchannel"}];
}
Create a CFM that allows the user to subscribe to the channel, with the selector condition value greater than the specified value, for example you want to see only the stock values above a particular threshold value.
<script type="text/javascript">
function msgHandler(messageobj)
{
if (messageobj.data != null) {
var ouputdiv = document.getElementById("myDiv");
var message = messageobj.data;
ouputdiv.innerHTML += message + "<br >" + "<br>";
}
}
function subscribeMe()
{
var amt = document.getElementById("amount").value;
var selectstring="value gt "+ amt;
TestSocket.subscribe("selectorchannel", {selector : selectstring});
document.getElementById("stocksSubscribe").style.display = 'none';
document.getElementById("l1").style.display = 'none';
document.getElementById("l2").style.display = 'block';
document.getElementById("publisme").style.display = 'block';
}
function publishme()
{
var amt = document.getElementById("amount").value;
TestSocket.publish("selectorchannel","Value is " +amt,{value: amt})
}
</script>
<cfwebsocket name="TestSocket" onMessage="msgHandler"/>
<br />
<lablel id="l1">Stock value above which you want to recieve message</lablel>
<label id="l2" style="display:none;">Value</label>
<input id="amount" name="amount" type="text">
<br>
<input id="stocksSubscribe" type="button" value="Subscribe" onclick="subscribeMe();">
<input id="publisme" type="button" value="Publish" onclick="publishme();" style="display:none;">
<div id="myDiv"></div>
You can specify the authentication details for WebSocket at the application level. An application method OnWSAuthenticate has been added to support application level authentication.
In the Application.cfc, define the function onWSAuthenticate.
Call the JavaScript function authenticate. This function calls the onWSAuthenticate function.
You cannot restrict authentication to a specific channel. If you do not want to authorize the client to any channels, it can be done using the allowSubscribe function of channel listener.
Description
Syntax
OnWSAuthenticate(username, password, connectionInfo)
Parameters
|
Parameter |
Description |
|---|---|
|
username |
Name of the user that has to be authenticated. |
|
password |
Password for the user. |
|
connectionInfo |
A struct that contains the following keys:
|
Custom keys are also supported. For example, you can specify the user's role, status, or age.The connectionInfo is shared across all the channels for a given WebSocket client. Also, modifications are persisted across all the subscriptions for that client.|
The following example uses the function onWSAuthenticate, validates the user, and associates a user role.
For this example to work, ensure that you implement the user-defined functions.
{
this.name="websocketsampleapp23";
this.wschannels=[{name="stocks",cfclistener="stocksListener"}];
function onWSAuthenticate(username, password, connectionInfo)
{
//write appropriate logic to fetch user password in funtion checkPassword
If(checkPassword(username) eq password)
{
connectionInfo.authenticated="YES";
//Role is the custom information that you provide
connectionInfo.role= "admin";
return true;
}
else{
connectionInfo.authenticated="NO";
return false;
}
writedump("#connectionInfo#","console");
}
}
If already authenticated to the ColdFusion server, you need not enter the credentials while subscribing to a WebSocket channel. You need only specify useCFAuth = "true" in the tag cfwebsocket.
In the following example, a login page is created using the tag cflogin. After authentication, the client is subscribed to a channel. That is, the client does not pass the login credentials while subscribing. Here, the function onWSAuthenticate need not be set up or called using the JavaScript function authenticate.
Create a login page using the tag cflogin.
User: <input name="username" type="text" id="username" value="admin"><br> Pass: <input name="password" type="text" id="password"><br> <input type="submit" name="Submit" value="Submit"> </form> <cfif structKeyExists(form,"username")> <cflogout> <cfset r = "user"> <cfif FORM.username is "admin"> <cfset r = "admin"> </cfif> <cflogin idletimeout="1800"> <cfloginuser name = "#FORM.username#" password ="#FORM.password#" roles = #r#> </cflogin> <cfoutput>Authorized user: #getAuthUser()#</cfoutput><br> <cfoutput>Authorized role: #GetUserRoles()#</cfoutput><br> <cflocation url="index.cfm"> </cfif>
Create the Application.cfc with a channel shares, and listener channelListener.
{
this.name = "myssoexample";
this.wschannels = [ {name = "sso", cfclistener="ChannelListener"}];
}
Create a CFM that allows the user to subscribe to a channel and publish the message.
var mycbHandler = function(msg)
{
if(msg.data)
{
var messageObject = msg.data;
var txt=document.getElementById("myDiv");
if((messageObject.indexOf("{")!=-1)){
var jsonValue = (new Function( "return( " + messageObject + " );" ))();
if(jsonValue){
txt.innerHTML+="<br>Authenticated : " + jsonValue.authenticated;
txt.innerHTML+="<br>UserName : " + jsonValue.username;
txt.innerHTML+="<br>Role : " + jsonValue.roles;
}
}
}
}
var openHandler = function()
{
mysock.publish("sso","hii");
}
</script>
<form name="f">
<cfwebsocket name="mysock" onMessage="mycbHandler" subscribeto="sso" onOpen="openHandler" useCFAuth="yes"/>
<div id="myDiv"></div>
</form>
Create a ColdFusion listener file that returns the subscriber information while publishing.
{
public any function beforeSendMessage(any message, Struct subscriberInfo)
{
writedump(var=subscriberInfo.connectionInfo, output="console");
return subscriberInfo.connectionInfo;
}
}
WebSocket server-side APIs allow a CFC to communicate with a channel or a specific client. For example, when a message is received from the client, the server sends a specific message.
The following table details the server-side functions:
|
Function Name |
Syntax |
Description |
|---|---|---|
|
WSgetSubscribers |
WSgetSubscribers (channel) |
Returns an array of struct with clientID and subcriberInfo as the keys. |
|
WSPublish |
WSPublish(channel, message [, filterCriteria]) |
Sends messages to a specific channel. Optionally, you can specify a filter criteria struct. |
|
WSGetAllChannels |
WSGetAllChannels () |
Provides all the channels defined in the Application.cfc as an array. |
The following is a sample response that you receive from the server:
{"clientid":2077108630,"ns":"coldfusion.websocket.channels","reqType":"subscribe","code":0,"type":"response","msg":"ok"}
The table explains the response keys:
Key |
Description |
|---|---|
clientid |
Unique ID assigned to a client. |
ns |
ColdFusion WebSocket namespace |
reqType |
The type of request represented by the JavaScript functions (for example, publish, or invokeandpublish). |
code |
See <code section> |
type |
Either response or data.
|
msg |
Applies to responses; ok if successful. On failure, returns the cause of failure. |
subscriberCount |
An integer that stands for the subscriber count. |
channels |
Applies to getSubscriptions, list of all subscribed channels. |
data |
Message is conveyed through data. |
publisherID |
Client ID of the publisher. If the message is from WSPublish, the ID is 0. |
channelname |
Name of the channel. |
The following is a sample subscribeto response sent to the message handler:
{"clientid":2077108664,"ns":"coldfusion.websocket.channels","channelsnotsubscribedto":"stocks.a","reqType":"subscribeTo","code":0,"type":"response","msg":"Subscription failed for channel(s) 'stocks.a'.","channelssubscribedto":"stocks"}
In this case, you have the key channelssubscribedto and channelsnotsubscribedto which applies to scenarios related to the attribute subsscribeTo in the tag cfwebsocket.
Sign in to your account