How to open multiple WebSockets

MiServer is Dyalog's APL-based web development framework
Post Reply
User avatar
PGilbert
Posts: 440
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada

How to open multiple WebSockets

Post by PGilbert »

What is the best way to open multiple WebSockets while using the HTMLRenderer in v18 ?

While you do in APL:
      InterceptedURLs←1 2⍴'ws://dyalog_root/' 1


and you do in JavaScript:

Code: Select all

ws1 = new WebSocket("ws://dyalog_root/");
ws2 = new WebSocket("ws://dyalog_root/");


what would be the way to differentiate that the WebSocketUpgradeEvent is coming from 'ws1' or 'ws2' ? I have tried adding something after the url (like: new WebSocket("ws://dyalog_root/ws1") but it does not show up in the url in APL).

Thanks in advance.
User avatar
Brian|Dyalog
Posts: 120
Joined: Thu Nov 26, 2009 4:02 pm
Location: West Henrietta, NY

Re: How to open multiple WebSockets

Post by Brian|Dyalog »

Hi Pierre!

First, I was surprised to see that the URL that's specified in the call to new WebSocket() isn't reflected in the callback arguments in APL. I've reported this as a bug. That would have been the easiest, and in my opinion, the most obvious way to differentiate between WebSockets. However, I would recommend setting a wildcard in InterceptedURLs as in (1 2⍴'ws://dyalog_root/*' 1). Then, if the URL was properly sent, you could do:

Code: Select all

ws1 = new WebSocket("ws://dyalog_root/ws1")
ws2 = new WebSocket("ws://dyalog_root/ws2")

Until the actual URL is send as a part of the callback, I can think of a couple ways to differentiate between multiple WebSockets. The first is to send an identifying message immediately after opening the WebSocket. You have the WebSocket ID from the WebSocketUpgrade and WebSocketReceive events so you can keep track of as many WebSockets as you want.

The second method involves specifying a subprotocol when you create the WebSocket. In this instance, the subprotocol is nothing more than a differentiator for a WebSocket. There is a registry of subprotocols, so it's good practice to name your subprotocol something unique to your application. This is a bit more involved because the WebSocketUpgrade request needs to be manually validated. This is specified by setting a value of 2 in the second column of InterceptedURLs. In your JavaScript, you specify the subprotocol (do something like:

Code: Select all

ws1 = new WebSocket("ws://dyalog_root/","pierre.ws1")
ws2 = new WebSocket("ws://dyalog_root/","pierre.ws2")

In APL:
  • You need to set the second element of the InterceptedURLs entry to 2

    Code: Select all

         iURLs←('InterceptedURLs'(1 2⍴'ws://dyalog_root/*' 2))
  • In the WebSocketUpgrade event handler, inspect the Sec-WebSocket-Protocol to determine which WebSocket is being upgraded

    Code: Select all

         :Case 'WebSocketUpgrade'
             (obj ev wsid url hdr)←5↑args
             protocol←⊃'^Sec-WebSocket-Protocol: (.*)' ⎕S '\1'⊢hdr  ⍝ note ⎕ML←1 here
  • In the WebSocketUpgrade event handler result, you need to supply a Sec-WebSocket-Protocol header that matches the subprotocol in the request

    Code: Select all

             hdr←'Sec-WebSocket-Protocol: ',protocol,⎕UCS 13 10
             resp←obj ev wsid url hdr
I hope this helps!
/Brian
User avatar
PGilbert
Posts: 440
Joined: Sun Dec 13, 2009 8:46 pm
Location: Montréal, Québec, Canada

Re: How to open multiple WebSockets

Post by PGilbert »

Thanks Brian, this is answering perfectly my question.
Post Reply