Online example: http://basic4ppc.com:51042/chat/index.html
This example demonstrates several important concepts of the web app framework.
The chatroom is made of two pages. The login page and the chat page.
The WebSocket is broken when the browser navigates to a different page (or refreshes the current page). The http session allows us to pass data from one page to another. In this example the user name is stored in the login page and then retrieved in the chat page:
If ws.Session.HasAttribute("name") = False Then
'name not found. Go to the login page. This will happen if the user goes to the chat page directly.
name = ws.Session.GetAttribute("name")
ws.Session.RemoveAttribute("name") 'remove the attribute
'the user will be redirected to the login page next time.
CallSubDelayed3(ChatShared, "NewConnection", Me, name)
Each WebSocket class instance runs in a different thread (in release mode). This allows many users to be connected at the same time.
CallSubDelayed was modified in B4J v2.00 to be executed on the target object thread. This allows us to safely call subs in other modules or instances.
In this example we have a code module named ChatShared. This module holds references to all the active connections and whenever there is a new message it uses CallSubDelayed to notify each of the instances about the new message:
'ChatShared code module
'notify each of the connected users about the new message
For Each c As Chat In connections.Values
CallSubDelayed2(c, "NewMessage", msg)
'Chat WebSocket class
Sub NewMessage(Msg As String)
ChatTxt.RunMethod("append", Array As Object(Msg))
The code in code modules will run in the main thread if we call it with CallSubDelayed.
In this example we call WebUtils methods directly as these methods do not rely on any shared data.
One of the great features of WebSockets is the simple support for server events. Unlike ajax based solutions, the clients don't need to poll the server with endless requests. At any given time the server can send messages to the client.
There is one extra step with server events. You must call ws.Flush at the end of the event. Flush is called internally in the case of client events.