Changes

Jump to navigation Jump to search
3,047 bytes added ,  16:57, 1 October 2018
no edit summary
The WebSocket protocol was standardized in [https://tools.ietf.org/html/rfc6455 RFC 6455] by the IETF. After an initial HTTP-request, all communication takes place over a single TCP connection. In contrast to the HTTP protocol, a connection will be kept alive, and a server can send unsolicited data to the client.
For establishing a WebSocket connection, a handshake request is sent by the client. The web server returns a handshake response. If the handshake is successful, the persistent connection will be open until an the client or the server closes it, an error occurs or a timeout happens. The timeout can be specified in the <code>web.xml</code> configuration file. It is possible to transmit all kind of data, binary or text.
=Introduction=
To speed up processing, the functions of the existing XQuery modules are automatically cached in main memory. For further information on cache handling, check out the [[RESTXQ#Introduction|RESTXQ introduction]].
 
==Examples==
 
<pre class="brush:xquery">
module namespace page = 'http://basex.org/modules/web-page';
 
import module namespace ws = "http://basex.org/modules/Websocket";
 
declare
%ws:connect("/")
function page:connect(
) {
(: Do something after a client connects to the path "/" :)
};
 
declare
%ws:message("/","{$message}")
function page:message(
$message as xs:string
) {
(: Do something if a message arrives at the server :)
};
 
declare
%ws:close("/")
function chat:close() {
(: Return a close message with the id of the client who closes the connection :)
let $client-id := ws:id()
let $msg := json:serialize(
<json type="object">
<type>WebsocketClosed</type>
<idThatClosed>{$client-id}</idThatClosed>
</json>
)
(: Broadcast the message to all connected users except the client who closes the connection :)
return ws:broadcast($msg)
};
</pre>
=Usage=
* Enable the WebSocket servlet in the <code>web.xml</code>. You can set here the maxIdleTime, maxTextMessageSize and maxBinaryMessageSize here too.* If you get a message that exceeds the maxTextMessageSize/maxBinaryMessageSize or, if not set, the default messageSize of Jetty of 65 536 bytes (64 kB) then the connection will closebe closed. In this case, the <code>ws:error </code> annotation will be called.
<pre class="brush:xml">
=Parameters=
* Http-Version -> f.e.: ```<code>%ws:param("Http-Version", "{$version}")```</code>
* Origin
* Protocol-Version
* For interacting with other clients or manage specific clients you should check out the [[WebSocket Module]] as well.
* The results of functions annotated with <code>%ws:close</code> or <code>%ws:error</code> will not be transmitted to the client
* For keeping the connection alive it is possible to implement heart-beats
* Use <code>wss</code> instead of <code>ws</code> for a secure WebSocket connection
* If you use a proxy server, check its configuration if WebSocket support is enabled
 
=Example=
The following chapter explains how to create a simple basic webapplication with websockets.
You can find another example in the BaseX source code.
First of all include the WsServlet in your <code>web.xml</code>.
 
<pre class="brush:xml">
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>BaseX: The XML Database and XQuery Processor</display-name>
<description>HTTP Services</description>
<!-- Global session and servlet listener -->
<listener>
<listener-class>org.basex.http.SessionListener</listener-class>
</listener>
<listener>
<listener-class>org.basex.http.ServletListener</listener-class>
</listener>
 
<!-- WebSocket Service (can be disabled by removing this entry) -->
<servlet>
<servlet-name>WebSocket</servlet-name>
<servlet-class>org.basex.http.ws.WsServlet</servlet-class>
<init-param>
<param-name>maxTextMessageSize</param-name>
<param-value>3000</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>WebSocket</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
 
<!-- Mapping for static resources (may be restricted to a sub path) -->
<servlet>
<servlet-name>default</servlet-name>
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
</web-app>
</pre>
 
For establishing a connection to the WebSocket server it is necessary that the server provides at least a function annotated with <code>%ws:connect("/")</code>.
The connect function can set WebSocket specific attributes like the id and name, emit a message to other connected users, write database entries, do nothing, ...
<pre class="brush:xquery">
declare
%ws:connect('/')
function example:connect() as empty-sequence() {
()
};
</pre>
 
With the state until now you can create a connection between client and server.
For doing sth. senseful with the WebSocket connection you should implement a function annotated with <code>%ws:message("/")</code>.
<pre class="brush:xquery">
import module namespace ws = 'http://basex.org/modules/ws'
declare
%ws:message('/', '{$message}')
function example:message(
$message as xs:string
) as empty-sequence() {
ws:emit($message)
};
</pre>
In the function above the WebSocketModule function <code>emit</code> is used for forwarding the message to all connected clients. Notice that you have to import the [[WebSocket Module]] before using it.
 
It is possible now to write client functions which connect to a WebSocket, send messages to the WebSocket and receive messages from the WebSocket.
The following client example provides basic code for handling the WebSocket connection.
 
<pre>
var ws = new WebSocket("wss://localhost:8984/ws");
ws.onmessage = function(event) {
alert(event.data);
};
 
function send(message) {
ws.send(message);
};
</pre>
 
There are no heart-beats in this example. This means that the connection is terminated if nothing happens for 5 minutes (standard timeout).
If you send a message which exceeds the textsize of 3kb defined in the <code>web.xml</code> the connection gets closed too.
administrator, editor
23

edits

Navigation menu