![]() | ||||||||||||||||||||
hello, world websocket in resin
A "hello, world" WebSocket servlet in Resin WebSocket is a new browser capability being developed for HTML 5 browsers, enabling fully interactive applications. With WebSockets, both the browser and the server can send asynchronous messages over a single TCP socket, without resorting to long polling or comet. Essentially, a WebSocket is a standard bidirectional TCP socket between the client and the server. The socket starts out as a HTTP connection and then "Upgrades" to a TCP socket after a HTTP handshake. After the handshake, either side can send data. WebSocket handshake GET /test HTTP/1.1 Upgrade: WebSocket Connection: Upgrade Origin: http://localhost/test Host: localhost Content-Length: 0 ... HTTP/1.1 101 Web Socket Protocol Handshake Upgrade: WebSocket Connection: Upgrade Server: Resin/4.0.2 WebSocket-Location: ws://localhost/websocket WebSocket-Origin: http://localhost/test Content-Length: 0 Date: Fri, 08 May 2009 09:51:31 GMT ... WebSocket packetsAfter the WebSocket connection is established, all data is encoded in lightweight packets. While the spec defines a text packet and a binary packet format, browsers use the text packet exclusively. (Resin's HMTP uses the binary packet format.) A text packet is the byte 0x00 followed by UTF-8 encoded data followed by a 0xff byte. WebSocket text packet x00 utf-8-data xff Example: hello text packet \x00hello, world\xff Since the tutorial is a hello, world, the JavaScript just does the following:
The JavaScript for this example has been tested with the nightly build of Chromium. Connecting to the WebSocket in JavaScriptExample: WebSocket connect in JavaScript
<?php
$url = "ws://localhost:8080/example/websocket";
?>
<script language='javascript'>
function onopen(event) { ... }
function onmessage(event) { ... }
function onclose(event) { ... }
ws = new WebSocket("<?= $url ?>");
wsopen.ws = ws;
ws.onopen = wsopen;
ws.onmessage = wsmessage;
ws.onclose = wsclose;
</script>
Receiving WebSocket data in JavaScriptExample: receive WebSocket message
<script language='javascript'>
function wsmessage(event)
{
data = event.data;
alert("Received: [" + data + "]");
}
</script>
Sending WebSocket data in JavaScriptExample: send WebSocket message
<script language='javascript'>
function wsopen(event)
{
ws = this.ws;
ws.send("my-message");
}
ws = new WebSocket(...);
wsopen.ws = ws;
ws.onopen = wsopen;
</script>
Resin's WebSocket support is designed to be similar to the Servlet 3.0 Async API, although the requirements for WebSockets are significantly different. To upgrade a HTTP socket to WebSocket, the ServletRequest is cast to a WebSocketServletRequest (implemented by Resin), and then call startWebSocket(...) Example: Upgrading to WebSocket
import com.caucho.servlet.WebSocketServletRequest;
import com.caucho.servlet.WebSocketListener;
...
public class MyServlet extends GenericServlet {
public void service(ServletRequest req, ServletResponse res)
throws IOException, ServletException
{
WebSocketServletRequest wsReq = (WebSocketServletRequest) req;
WebSocketListener handler = new MyHandler();
wsReq.startWebSocket(handler);
}
}
The WebSocketListener is the heart of the server-side implementation of websockets. It is a single-threaded listener for client events. When a new packet is available, Resin will call the In this example, the handler reads a WebSocket text packet and sends a response. The Example: MyHandler.java
package example;
import com.caucho.servlet.WebSocketContext;
import com.caucho.servlet.WebSocketListener;
public class MyHandler implements WebSocketListener
{
...
public void onRead(WebSocketContext context)
throws IOException
{
StringBuilder sb = new StringBuilder();
InputStream is = context.getInputStream();
OutputStream os = context.getOutputStream();
int ch = _is.read();
assert(ch == 0x00); // packet starts with 0x00
while ((ch = _is.read()) >= 0 && ch != 0xff) {
sb.append((char) ch);
}
String message = sb.toString();
String result = "received message";
_os.write(0x00);
_os.write(result.getBytes("utf-8"));
_os.write(0xff);
_os.flush();
}
}
Resin's WebSocketListener has four callback methods. WebSocketListener.java
package com.caucho.servlet;
public interface WebSocketListener
{
public void onStart(WebSocketContext context) throws IOException;
public void onRead(WebSocketContext context) throws IOException;
public void onComplete(WebSocketContext context) throws IOException;
public void onTimeout(WebSocketContext context) throws IOException;
}
The WebSocket context gives access to the WebSocket streams, as well as allowing setting of the socket timeout, and closing the connection. WebSocketContext.java
package com.caucho.servlet;
public interface WebSocketContext
{
public InputStream getInputStream() throws IOException;
public OutputStream getOutputStream() throws IOException;
public void setTimeout(long timeout);
public long getTimeout();
public void complete();
}
| ||||||||||||||||||||