Processing Text and Binary (Blob, ArrayBuffer, ArrayBufferView) Payload in WebSocket - (TOTD #185)
- by arungupta
The WebSocket API
defines different send(xxx) methods that can be used
to send text and binary data. This Tip Of The
Day (TOTD) will show how to send and receive text and binary
data using WebSocket.
TOTD #183 explains how to get started with a WebSocket endpoint
using GlassFish 4. A simple endpoint from that blog looks like:
@WebSocketEndpoint("/endpoint")
public class MyEndpoint {
public void receiveTextMessage(String message) {
. . .
}
}
A message with the first parameter of the type String
is invoked when a text payload is received. The payload of the
incoming WebSocket frame is mapped to this first parameter.
An optional second parameter, Session, can be
specified to map to the "other end" of this conversation. For
example:
public void receiveTextMessage(String message, Session session) {
. . .
}
The return type is void and that means no response is
returned to the client that invoked this endpoint. A response may be
returned to the client in two different ways. First, set the return
type to the expected type, such as:
public String receiveTextMessage(String message) {
String response = . . . . . . return response;
}
In this case a text payload is returned back to the invoking
endpoint.
The second way to send a response back is to use the mapped session
to send response using one of the sendXXX methods in Session,
when and if needed.
public void receiveTextMessage(String message, Session session) {
. . .
RemoteEndpoint remote = session.getRemote();
remote.sendString(...);
. . .
remote.sendString(...);
. . .
remote.sendString(...);
}
This shows how duplex and asynchronous communication between the two
endpoints can be achieved. This can be used to define different
message exchange patterns between the client and server.
The WebSocket client can send the message as:
websocket.send(myTextField.value);
where myTextField is a text field in the web page.
Binary payload in the incoming WebSocket frame can be received if ByteBuffer
is used as the first parameter of the method signature. The endpoint
method signature in that case would look like:
public void receiveBinaryMessage(ByteBuffer message) {
. . .
}
From the client side, the binary data can be sent using Blob,
ArrayBuffer, and ArrayBufferView. Blob is
a just raw data and the actual interpretation is left to the
application. ArrayBuffer and ArrayBufferView
are defined in the TypedArray
specification and are designed to send binary data using
WebSocket. In short, ArrayBuffer is a fixed-length
binary buffer with no format and no mechanism for accessing its
contents. These buffers are manipulated using one of the views
defined by one of the subclasses of ArrayBufferView
listed below:
Int8Array (signed 8-bit integer or char)
Uint8Array (unsigned 8-bit integer or unsigned
char)
Int16Array (signed 16-bit integer or short)
Uint16Array (unsigned 16-bit integer or unsigned
short)
Int32Array (signed 32-bit integer or int)
Uint32Array (unsigned 16-bit integer or unsigned
int)
Float32Array (signed 32-bit float or float)
Float64Array (signed 64-bit float or double)
WebSocket can send binary data using ArrayBuffer with
a view defined by a subclass of ArrayBufferView or a
subclass of ArrayBufferView itself.
The WebSocket client can send the message using Blob as:
blob = new Blob([myField2.value]);websocket.send(blob);
where myField2 is a text field in the web page.
The WebSocket client can send the message using ArrayBuffer
as:
var buffer = new ArrayBuffer(10);var bytes = new Uint8Array(buffer);for (var i=0; i<bytes.length; i++) { bytes[i] = i;}websocket.send(buffer);
A concrete implementation of receiving the binary message may look
like:
@WebSocketMessagepublic void echoBinary(ByteBuffer data, Session session) throws IOException { System.out.println("echoBinary: " + data); for (byte b : data.array()) { System.out.print(b); } session.getRemote().sendBytes(data);}
This method is just printing the binary data for verification but
you may actually be storing it in a database or converting to an
image or something more meaningful.
Be aware of TYRUS-51
if you are trying to send binary data from server to client using
method return type.
Here are some references for you:
JSR 356:
Java API for WebSocket - Specification (Early
Draft) and Implementation
(already integrated in GlassFish
4 promoted builds)
TOTD
#183 - Getting Started with WebSocket in GlassFish
TOTD
#184 - Logging WebSocket Frames using Chrome Developer
Tools, Net-internals and Wireshark
Subsequent blogs will discuss the following topics (not necessary in
that order) ...
Error handling
Custom payloads using encoder/decoder
Interface-driven WebSocket endpoint
Java client API
Client and Server configuration
Security
Subprotocols
Extensions
Other topics from the API