The web makes use of a request / response approach to communication between
the server and the client. The client (usually a browser) makes a request to
the server, and gets a response. The connection between the client and the
server is then closed (either immediately or after a short period of time.)
Because of this architecture the server can efficiently deal with large
numbers of users. Very few, if any, server side resources are consumed, even
for very large numbers of users.
Unfortunately this also means the
server cannot "push" data to the client. If something on the server side
changes then there's no way to push that update to the client, because there
is no connection to the client.
For this reason it would be
advantageous in some cases to have an open connection to the server, one
which stays open, over which the server could "push" updated information to
the client. The "cost" of this approach is that an open connection is
maintained between the server and the client, which naturally then uses up
an available connection on the server side.
This technology was added
to the web standards in late 2011 and rolled in browsers sometime after
that. Today most browsers support WebSockets.
NetTalk 9 introduced
limited web socket functionality for the Server side. NetTalk 10 expands on
the server side, and also adds WebSocket support to the client-side.
WebSocket client support is included in
NetTalk Desktop. Server and Client support is included in NetTalk Server.
A WebSocket client object can be added to a window. This object allows you
to communicate with any WebSocket server. Use of the object is fairly simple
only a handful of methods are involved. The class to use is
NetWebSocketClient.
Connecting
To connect to a server the
connect method is used. This takes a single parameter, the URL to connect
to. The URL does not need to contain the protocol (ws:// or wss://) - if
this is omitted then an insecure connection (ws://) is assumed (unless the
SSL property has been set to true.) For
convenience if http:// or https:// are used then these are treated as ws://
or wss:// respectivly.
for example
net.start()
net.connect('ws://www.capesoft.com')
or
net.start()
net.connect('wss://www.capesoft.com')
or
net.start()
net.SSL = true
net.connect('www.capesoft.com')
Remember that a connection is asynchronous, so this will initiate a
connection, however a connection has not yet been established. When
the connection is established then the OnOpen
method will be called. (OnOpen is called
again if the connection is lost, and reopened.)
Once
the connection is open then you can send messages to the server using either
the SendText or SendBinary
methods.
If you are communicating with a NetTalk Web
Server, which supports WebSockets, then a few more methods,
which provide some higher-level functionality are also available.
Aside: While the protocol should be ws: or
wss: the object is smart enough to also
accept http: or https:
- it translates these to ws: and
wss: as required.
If a connection
fails to open (because the server is not listening at the moment of
open) and the AutoReconnect property is true
(which is is by default) then the connection will automatically go into
a reconnecting state and will continue to attempt to open (as per the
reconnecting rules below) until the Close method is called.
Reconnecting
The WebSocket protocol supports PING and PONG messages to keep the
connection alive, and to check to see if the connection is alive.
Support for these messages is built-in, you do not need to do anything
to support them.
If a connection to a server is unexpectedly lost
(and the AutoReconnect property is true,
which it is by default) then the client will automatically try and
reconnect to the server. During this time the
TryingToReconnect property is set to true. (TryingToReconnect
is set to false once a connection to the server is made.) The time between tries is determined by the
PingInterval property. This is (by default)
set to 27 seconds. Events trigger the check, and the slowest event (the
timer) is set to 13.5 seconds. So the maximum period between connection
retries is (by default) is 40.5 seconds.
When a connection is opened, or lost, or re-opened then the
ConnectionStateChanged method is called.
This allows you to embed code in your procedure that changes a visual
cue, or some other effect, that lets the user know the state of the
connection. The ConnectionStateChanged method takes a parameter
called pState, a LONG
value which is one of netState:Open,
netState:Handshaking or
netState:Closed.
Reconnecting only takes place if the
connection is lost unexpectedly. If you close manually (by calling
close or disconnect)
then a reconnection is not attempted. Some servers will pass a message
before closing indicating that reconnecting is not desired. In these
cases you can set the AutoReconnect property
to false.
If an open, or reconnection is successful then the
OnOpen method is called.
Sending Messages
Messages can be set as either Text values, or Binary values. The server
you are talking to will indicate which one is preferred. In most cases
the server will default to accepting text messages.
To send a
Text message use the SendText method. This takes
a String, or a StringTheory
object,
as the parameter. The object contains the text to send.
To send
a Binary message use the SendBinary method. This also takes
either a String or a StringTheory
object as the parameter.
Receiving Messages
When a complete message is received then the
ProcessMessage method is called. This method takes two
parameters, a Long for the Message Type and a
StringTheory object
containing the message.
The Message Type will be one of
NetOpCode:TextFrame,
NetOpCode:BinaryFrame or
NetOpCode:ConnectionClose.
You can process the message
inside the method, doing whatever it is you need to do.
Disconnect
To disconnect from the server call the Close method.
JSON
Messages can contain
any text or binary information. What you send to the server, and what
the server sends to you is completely arbitrary, and can be in any format
that you both agree to.
Most servers will use JSON when moving
text messages to and from a client. These can be easily constructed, and
parsed by both ends, so makes for a very convenient mechanism. While
JSON is a common format for formatting text messages, any other
formatting of text messages is possible.
The NetWebSocketClient class described above is suitable for use against
any server which supports the ws protocol. However each server will
support different commands and responses. The developer will need to
format packets to send, and also embed code in the
ProcessMessage
method to manage that protocol.
NetWebSocketClientNetWebServer
Class
NetTalk Web Servers support a
simple text protocol for some common functionality. The
NetWebSocketClientNetWebServer class is derived from the regular
NetWebSocketClient class, but adds a few more methods to more easily
make use of this server side functionality. This class is only
useful when talking to NetTalk Web Servers. For other servers use the
NetWebSocketClient class.
Of course the underlying SendText and
SendBinary methods still exist in the NetWebSocketClientNetWebServer
class so you can still use this class to further extend the
functionality of your server/client combination.
The
NetTalk Server allows you to easily watch server values and channels. If
you register as a client then anytime those values change you will be
notified.
Host Value
A Host Value is a variable on the server that is global to all
users.
The program can watch this variable, in which case if it
is changed by the server, or by another user, the new value will
be sent to the program. If you have assigned a client-side
variable when doing the watch then any changes on the server
side will reflect on the client side (with no embed code
required.)
The program can also set
this variable. Once set the server will send it to any other
program that is watching the variable.
For example;
WebPerformance
Group,pre(wp)
NumberOfRequests
Long
NumberOfSpiderRequests Long
End
net.WatchHostValue('WebPerformance',WebPerformance)
In this example two server-side Host variables (wp:NumberOfRequests
and wp:NumberOfSpiderRequests) will
be monitored. If the server side value changes then the client
side value, in the group, will also change. A change will also
trigger a notification to the
ReceiveHostValue method where custom embed code can be
added.
The second parameter to WatchHostValue is optional. If it is
omitted then only a notification will be sent to the
ReceiveHostValue method.
Aside: In order for a Host Value on the server to change,
someone has to change it. It can be changed by a client, or it
can be changed by the server itself. In the above example, where
clients are monitoring server performance, it would need code in
the server to update these host values. However if two clients
were connected to the same server, they could update the host
values themselves, and all the other clients monitoring these
values would also change. In this case no server code would be
involved.
Channel
A Channel is similar to a Host value except that
it allows for more limited scoping. Where a host variable is
shared across all users, a channel can be shared among just some
users. This is done by giving the Channel a Group name.
Users using the same Group will see values from other users
using the same Group.