Skip to content

Example Chat

Igal edited this page May 28, 2017 · 18 revisions

This example shows how to write a multi-channel Chat Server using the Lucee WebSocket Extension. The example consists of 3 files, but its core is the file ChatListener.cfc.

In this example we use the path-parameter {channel} in the endpoint (/ws/chat/{channel}), which automatically subscribes every incoming connection to the channel specified by the URL's path parameter, e.g. a connection to /ws/chat/support will be subscribed to the channel support.

To run the example, call index.cfm with a username URL parameter to set the username, e.g. index.cfm?username=Lucy, and a an optional channel parameter, e.g. index.cfm?username=Lucy&channel=support.

Then use the JavaScript object wschat according to the JavaScript WebSocket API

ChatListener.cfc

The main file in this example is ChatListener.cfc which implements the Listener Component API:

/** ChatListener.cfc */
component {

    /**
    * Ensures that we have a valid Session.username, and notifies the channel
    * subscribers that the user connected
    */
    function onOpen(websocket, endpointConfig, sessionScope, applicationScope){

        if (isEmpty(arguments.sessionScope.username ?: ""))
            return false;        // returing false will reject the connection

        this.notifyChannel(
             arguments.websocket
            ,{
                 from   : "<server>"
                ,message: "#arguments.sessionScope.username# connected"
            }
        );
    }

    /**
    * Notifies the channel subscribers to the channel that the user has disconnected
    */
    function onClose(websocket, closeReason, sessionSCope, applicationScope){

        this.notifyChannel(
             arguments.websocket
            ,{
                 from   : "<server>"
                ,message: "#arguments.sessionScope.username# disconnected"
            }
        );
    }

    /**
    * Broadcasts the message to the channel's subscribers
    */
    function onMessage(websocket, message, sessionScope, applicationScope){

        this.notifyChannel(
             arguments.websocket
            ,{
                 from   : arguments.sessionScope.username
                ,message: arguments.message
            }
        );
    }

    /**
    * This is a helper method that adds a timestamp to the data, serializes
    * it as JSON, and broadcasts it to all of the subscribers to the channel
    * of this websocket connection
    */
    private function notifyChannel(websocket, data){

        var chanId  = arguments.websocket.getPathParameters().channel;
        var connMgr = arguments.websocket.getConnectionManager();
        arguments.data.channel   = chanId;
        arguments.data.timestamp = getTickCount();

        connMgr.broadcast(chanId, serializeJson(arguments.data));
    }
}

Application.cfc

As before, we use Application.cfc's onApplicationStart() to register the websocket endpoint, /ws/chat/{channel}, with an instance of ChatListener.cfc.

component {

    this.name = "websocket_chat";

    function onApplicationStart(){

        WebsocketRegister("/ws/chat/{channel}", new ChatListener());
    }
}

index.cfm

This is a simple page that creates a JavaScript WebSocket client and connects to the server:

<cfscript>
    /** ensure that we have Session.username and set a default channel */

    if (!isNull(URL.username))
        Session.username = URL.username;

    if (isEmpty(Session.username ?: "")){

        echo("<p>Session.username is not defined. Set it using the URL parameter username, e.g. ?username=Lucy");
        abort;
    }

    param name="channel" default="default";
</cfscript>


<cfoutput>
    <!--- JavaScript follows !--->
    <script>
        var channel  = "#channel#";
        var endpoint = "/ws/chat/" + channel;
        var protocol = (document.location.protocol == "https:") ? "wss://" : "ws://";

        var wschat   = new WebSocket(protocol + document.location.host + endpoint);

        var log = function(evt){
            console.log(evt.data ? JSON.parse(evt.data) : evt);
        };
        wschat.onopen    = log;
        wschat.onmessage = log;
        wschat.onerror   = log;
        wschat.onclose   = log;

        document.title   = `#Session.username# on ${channel}`;
        document.write(`<p>[wschat] connected to "${channel}" as "#Session.username#"`);
    </script>
</cfoutput>

Watch Chat Server Example Video Tutorial at:

Chat Server Example Video

Clone this wiki locally