Writing WebSocket client applications

  • Revision slug: WebSockets/Writing_WebSocket_client_applications
  • Revision title: Writing WebSocket client applications
  • Revision id: 732
  • Created:
  • Creator: gilesburdett
  • Is current revision? No
  • Comment one or more formatting changes

Revision Content

{{ draft() }}

WebSockets is a technology that makes it possible to open an interactive communication session between the user's browser and a server. Using a WebSocket connection, Web applications can perform real-time communication instead of having to poll for changes back and forth.

Note: We have a working example of the chat/server system used for code snippets that will be made available once our infrastructure is in place for hosting WebSocket examples properly.

Availability of WebSockets

The WebSocket API is available to JavaScript code whose scope is either a DOM {{ domxref("Window") }} object or any object implementing {{ domxref("WorkerUtils") }}; that is, you can use it from Web Workers.

Note: The WebSockets API (and the underlying protocol) are still in active development, and there are many compatibility issues across browsers at this time (and even among different releases of the same browser).

Creating a WebSocket object

In order to communicate using the WebSocket protocol, you need to create a WebSocket object; this will automatically attempt to open the connection to the server.

Note: Keep in mind that the WebSocket object is prefixed on Firefox 6.0, and that you need to use MozWebSocket there.

The WebSocket constructor accepts one required and one optional parameter:

WebSocket WebSocket(
  in DOMString url,
  in optional DOMString protocols
);

WebSocket WebSocket(
  in DOMString url,
  in optional DOMString[] protocols
);
url
The URL to which to connect; this should be the URL to which the WebSocket server will respond.
protocols {{ optional_inline() }}
Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols, so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified protocol). If you don't specify a protocol string, an empty string is assumed.

The constructor can throw exceptions:

SECURITY_ERR
The port to which the connection is being attempted is being blocked.

Connection errors

If an error occurs while attempting to connect, a simple event with the name "error" is sent to the WebSocket object (thereby invoking its onerror handler), and then the CloseEvent is delivered to indicate the reason for the connection's closing.

Examples

This simple example creates a new WebSocket, connecting to the server at ws://www.example.com/socketserver. A custom protocol of "protocolOne" is named in the request for the socket.

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", "protocolOne");

On return, exampleSocket.readyState is CONNECTING. The readyState will become OPEN once the connection is ready to transfer data.

If you want to open a connection and are flexible about the protocols you support, you can specify an array of protocols:

var exampleSocket = new WebSocket("ws://www.example.com/socketserver", ["protocolOne", "protocolTwo"]);

Once the connection is established (that is, readyState is OPEN), the protocol attribute will tell you which protocol the server selected.

In the above examples "ws" has replaced "http", similarly "wss" replaces "https". Establishing a WebSocket relies on the HTTP Upgrade mechanism, so the fully qualified domain name of the HTTP server is required, and the request for the protocol upgrade is implicit when we address the HTTP server as ws://www.example.com or wss://www.example.com.

Sending data to the server

Once you've opened your connection, you can begin transmitting data to the server. To do this, simply call the WebSocket object's send() method for each message you want to send:

mySocket.send("Here's some text that the server is urgently awaiting!"); 

You can send strings, {{ domxref("Blob") }}s, or ArrayBuffers.

Note: Firefox currently only supports sending strings.

Using JSON to transmit objects

One handy thing you can do is use JSON to send reasonably complex data to the server. For example, a chat program can interact with a server using a protocol implemented using packets of JSON-encapsulated data:

// Send text to all users through the server

function sendText() {
  var msg = {
    type: "message",
    text: document.getElementById("text").value,
    id: clientID,
    date: Date.now()
  };

  mySocket.send(JSON.stringify(msg));
  document.getElementById("text").value = "";
} 

This code constructs an object, msg, containing various pieces of data the server will need in order to process the message. Then it calls JSON.stringify() to convert the object to JSON format and calls the WebSocket send() method to transmit the data to the server.

Receiving messages from the server

WebSockets is an event-driven API; when messages are received, a "message" event is delivered to the onmessage function. To begin listening for incoming data, you can do something like this:

mySocket.onmessage = function(e) {
  console.log(e.data);
}

Receiving and interpreting JSON objects

Let's consider the chat client application first alluded to in {{ anch("Using JSON to transmit objects") }}. There are assorted types of data packets the client might receive, such as:

  • Login handshake
  • Message text
  • User list updates

The code that interprets these incoming messages might look like this:

connection.onmessage = function(evt) {
  var f = document.getElementById("chatbox").contentDocument;
  var text = "";
  var msg = JSON.parse(evt.data);
  var time = new Date(msg.date);
  var timeStr = time.toLocaleTimeString();
  
  switch(msg.type) {
    case "id":
      clientID = msg.id;
      setUsername();
      break;
    case "username":
      text = "<b>User <em>" + msg.name + "</em> signed in at " + timeStr + "</b><br>";
      break;
    case "message":
      text = "(" + timeStr + ") <b>" + msg.name + "</b>: " + msg.text + "<br>";
      break;
    case "rejectusername":
      text = "<b>Your username has been set to <em>" + msg.name + "</em> because the name you chose is in use.</b><br>"
      break;
    case "userlist":
      var ul = "";
      for (i=0; i < msg.users.length; i++) {
        ul += msg.users[i] + "<br>";
      }
      document.getElementById("userlistbox").innerHTML = ul;
      break;
  }
  
  if (text.length) {
    f.write(text);
    document.getElementById("chatbox").contentWindow.scrollByPages(1);
  }
};

Here we use JSON.parse() to convert the JSON object back into the original object, then examine and act upon its contents.

Text data format

Text received over a WebSocket connection is in UTF-8 format.

Prior to Gecko 9.0 {{ geckoRelease("9.0") }}, certain non-characters in otherwise valid UTF-8 text would cause the connection to be terminated. Now Gecko permits these values.

Closing the connection

When you've finished using the WebSocket connection, call the WebSocket method close():

mySocket.close();

Security considerations

WebSockets should not be used in a mixed content environment; that is, you shouldn't open a non-secure WebSocket conection from a page loaded using HTTPS or vice-versa. In fact, some browsers explicitly forbid this, including Firefox 8 and later.

{{ languages ( {"zh-tw": "zh_tw/WebSockets/Writing_WebSocket_client_applications"} ) }}

Revision Source

<p>{{ draft() }}</p>
<p>WebSockets is a technology that makes it possible to open an interactive communication session between the user's browser and a server. Using a WebSocket connection, Web applications can perform real-time communication instead of having to poll for changes back and forth.</p>
<div class="note"><strong>Note:</strong> We have a working example of the chat/server system used for code snippets that will be made available once our infrastructure is in place for hosting WebSocket examples properly.</div>
<h2>Availability of WebSockets</h2>
<p>The WebSocket API is available to JavaScript code whose scope is either a DOM {{ domxref("Window") }} object or any object implementing {{ domxref("WorkerUtils") }}; that is, you can use it from Web Workers.</p>
<div class="note"><strong>Note:</strong> The WebSockets API (and the underlying protocol) are still in active development, and there are many compatibility issues across browsers at this time (and even among different releases of the same browser).</div>
<h2>Creating a WebSocket object</h2>
<p>In order to communicate using the WebSocket protocol, you need to create a <a href="/en/WebSockets/WebSockets_reference/WebSocket" title="en/WebSockets/WebSockets reference/WebSocket"><code>WebSocket</code></a> object; this will automatically attempt to open the connection to the server.</p>
<div class="note"><strong>Note:</strong> Keep in mind that the <code>WebSocket</code> object is prefixed on Firefox 6.0, and that you need to use <code>MozWebSocket</code> there.</div>
<p>The WebSocket constructor accepts one required and one optional parameter:</p>
<pre>WebSocket WebSocket(
  in DOMString url,
  in optional DOMString protocols
);

WebSocket WebSocket(
  in DOMString url,
  in optional DOMString[] protocols
);
</pre>
<dl> <dt><code>url</code></dt> <dd>The URL to which to connect; this should be the URL to which the WebSocket server will respond.</dd> <dt><code>protocols</code> {{ optional_inline() }}</dt> <dd>Either a single protocol string or an array of protocol strings. These strings are used to indicate sub-protocols, so that a single server can implement multiple WebSocket sub-protocols (for example, you might want one server to be able to handle different types of interactions depending on the specified <code>protocol</code>). If you don't specify a protocol string, an empty string is assumed.</dd>
</dl>
<p>The constructor can throw exceptions:</p>
<dl> <dt><code>SECURITY_ERR</code></dt> <dd>The port to which the connection is being attempted is being blocked.</dd>
</dl>
<dl>
</dl>
<h3>Connection errors</h3>
<p>If an error occurs while attempting to connect, a simple event with the name "error" is sent to the <a href="/en/WebSockets/WebSockets_reference/WebSocket" title="WebSocket"><code>WebSocket</code></a> object (thereby invoking its <code>onerror</code> handler), and then the <a href="/en/WebSockets/WebSockets_reference/CloseEvent" title="CloseEvent"><code>CloseEvent</code></a> is delivered to indicate the reason for the connection's closing.</p>
<h3>Examples</h3>
<p>This simple example creates a new WebSocket, connecting to the server at <code><span class="nowiki">ws://www.example.com/socketserver</span></code>. A custom protocol of "protocolOne" is named in the request for the socket.</p>
<pre>var exampleSocket = new WebSocket("<span class="plain">ws://www.example.com/socketserver</span>", "protocolOne");
</pre>
<p>On return, <code>exampleSocket</code>.<code>readyState</code> is <code>CONNECTING</code>. The <code>readyState</code> will become <code>OPEN</code> once the connection is ready to transfer data.</p>
<p>If you want to open a connection and are flexible about the protocols you support, you can specify an array of protocols:</p>
<pre>var exampleSocket = new WebSocket("<span class="plain">ws://www.example.com/socketserver</span>", ["protocolOne", "protocolTwo"]);
</pre>
<p>Once the connection is established (that is, <code>readyState</code> is <code>OPEN</code>), the <code>protocol</code> attribute will tell you which protocol the server selected.</p>
<p>In the above examples "ws" has replaced "http", similarly "wss" replaces "https". Establishing a WebSocket relies on the HTTP Upgrade mechanism, so the fully qualified domain name of the HTTP server is required, and the request for the protocol upgrade is implicit when we address the HTTP server as <code><span class="nowiki">ws://www.example.com</span></code> or <code><span class="nowiki">wss://www.example.com</span></code>.</p><h2>Sending data to the server</h2>
<p>Once you've opened your connection, you can begin transmitting data to the server. To do this, simply call the <code>WebSocket</code> object's <a href="/en/WebSockets/WebSockets_reference/WebSocket#send()" title="en/WebSockets/WebSockets reference/WebSocket#send()"><code>send()</code></a> method for each message you want to send:</p>
<pre>mySocket.send("Here's some text that the server is urgently awaiting!"); 
</pre>
<p>You can send strings, {{ domxref("Blob") }}s, or <a href="/en/JavaScript_typed_arrays/ArrayBuffer" title="en/JavaScript typed arrays/ArrayBuffer"><code>ArrayBuffer</code></a>s.</p>
<div class="note"><strong>Note:</strong> Firefox currently only supports sending strings.</div>
<h3>Using JSON to transmit objects</h3>
<p>One handy thing you can do is use <a href="/en/JSON" title="en/JSON">JSON</a> to send reasonably complex data to the server. For example, a chat program can interact with a server using a protocol implemented using packets of JSON-encapsulated data:</p>
<pre class="brush: js">// Send text to all users through the server

function sendText() {
  var msg = {
    type: "message",
    text: document.getElementById("text").value,
    id: clientID,
    date: Date.now()
  };

  mySocket.send(JSON.stringify(msg));
  document.getElementById("text").value = "";
} 
</pre>
<p>This code constructs an object, <code>msg</code>, containing various pieces of data the server will need in order to process the message. Then it calls <a href="/en/JavaScript/Reference/Global_Objects/JSON/stringify" title="en/JavaScript/Reference/Global Objects/JSON/stringify"><code>JSON.stringify()</code></a> to convert the object to JSON format and calls the WebSocket <a href="/en/WebSockets/WebSockets_reference/WebSocket#send()" title="en/WebSockets/WebSockets reference/WebSocket#send()"><code>send()</code></a> method to transmit the data to the server.</p>
<h2>Receiving messages from the server</h2>
<p>WebSockets is an event-driven API; when messages are received, a "message" event is delivered to the <code>onmessage</code> function. To begin listening for incoming data, you can do something like this:</p>
<pre class="brush: js">mySocket.onmessage = function(e) {
  console.log(e.data);
}
</pre>
<h3>Receiving and interpreting JSON objects</h3>
<p>Let's consider the chat client application first alluded to in {{ anch("Using JSON to transmit objects") }}. There are assorted types of data packets the client might receive, such as:</p>
<ul> <li>Login handshake</li> <li>Message text</li> <li>User list updates</li>
</ul>
<p>The code that interprets these incoming messages might look like this:</p>
<pre class="brush: js">connection.onmessage = function(evt) {
  var f = document.getElementById("chatbox").contentDocument;
  var text = "";
  var msg = JSON.parse(evt.data);
  var time = new Date(msg.date);
  var timeStr = time.toLocaleTimeString();
  
  switch(msg.type) {
    case "id":
      clientID = msg.id;
      setUsername();
      break;
    case "username":
      text = "&lt;b&gt;User &lt;em&gt;" + msg.name + "&lt;/em&gt; signed in at " + timeStr + "&lt;/b&gt;&lt;br&gt;";
      break;
    case "message":
      text = "(" + timeStr + ") &lt;b&gt;" + msg.name + "&lt;/b&gt;: " + msg.text + "&lt;br&gt;";
      break;
    case "rejectusername":
      text = "&lt;b&gt;Your username has been set to &lt;em&gt;" + msg.name + "&lt;/em&gt; because the name you chose is in use.&lt;/b&gt;&lt;br&gt;"
      break;
    case "userlist":
      var ul = "";
      for (i=0; i &lt; msg.users.length; i++) {
        ul += msg.users[i] + "&lt;br&gt;";
      }
      document.getElementById("userlistbox").innerHTML = ul;
      break;
  }
  
  if (text.length) {
    f.write(text);
    document.getElementById("chatbox").contentWindow.scrollByPages(1);
  }
};
</pre>
<p>Here we use <a href="/en/JavaScript/Reference/Global_Objects/JSON/parse" title="en/JavaScript/Reference/Global Objects/JSON/parse"><code>JSON.parse()</code></a> to convert the JSON object back into the original object, then examine and act upon its contents.</p>
<h3>Text data format</h3>
<p>Text received over a WebSocket connection is in UTF-8 format.</p>
<p>Prior to Gecko 9.0 {{ geckoRelease("9.0") }}, certain non-characters in otherwise valid UTF-8 text would cause the connection to be terminated. Now Gecko permits these values.</p><h2>Closing the connection</h2>
<p>When you've finished using the WebSocket connection, call the WebSocket method <a href="/en/WebSockets/WebSockets_reference/WebSocket#close()" title="en/WebSockets/WebSockets reference/WebSocket#close()"><code>close()</code></a>:</p>
<pre>mySocket.close();
</pre>
<h2>Security considerations</h2>
<p>WebSockets should not be used in a mixed content environment; that is, you shouldn't open a non-secure WebSocket conection from a page loaded using HTTPS or vice-versa. In fact, some browsers explicitly forbid this, including Firefox 8 and later.</p>
<p>{{ languages ( {"zh-tw": "zh_tw/WebSockets/Writing_WebSocket_client_applications"} ) }}</p>
Revert to this revision