Portal has reached its End of Life and is no longer maintained! Use Use Cettia. ×

Protocol

Notice Will be rewritten introducing a test suite for server implementation.

URI

The socket URI to open a connection looks like the following:

chat?when=open&id=ed84f5a4-0772-43c6-ba95-e293c287be7c&transport=sse&heartbeat=false&lastEventId=25&_=1333818006226

The above URI is generated by urlBuilder option with the open when in the browser side and the following parameters are included in the form of query string by default.

  • when: The purpose of request. Always open when establishing a connection.
  • id: A unique socket identifier across the browser and the server.
  • heartbeat: A heartbeat interval. The value which is in a number format means that the browser will manage the connection using a heartbeat timer, and the value of false indicates no heartbeat.
  • transport: A required transport for the connection. It can have the following values unless you add or remove transport: ws, sse, streamxdr, streamiframe, streamxhr, longpollajax, longpollxdr and longpolljsonp.
  • lastEventId: An id of the last event the browser received via the previous connection. If it does not exist, the value will be 0 instead. If the server sends events in no order or asynchronously, this value could not be criterion for lost events.
  • _: A value to prevent the browser from caching a GET request.

Opening connection

Prepare event-driven server.

WebSocket

There is nothing you have to do.

Streaming

The HTTP method GET is used to establish a connection, and applied transports are sse, streamxdr, streamiframe and streamxhr. For the server, the Server-Sent Events is a kind of the streaming.

  • The response should be encoded in utf-8 format. - sse.
  • Access-Control-Allow-Origin header should be either * or the value of the Origin request header. - streamxdr.
  • The content-type header should be set to text/event-stream if the transport is sse and should be set to text/plain if not for streamiframe to prevent iframe tag from parsing response as HTML.
  • The padding is required, which makes the transport object in the browser side aware of change of the response. The padding should be greater than one kilobyte (4K for Android browser 2 and 3), be composed of white space characters and end with \r, \n or \r\n. The socket in the browser side fires the open event when noticing padding. - streamxdr, streamiframe, streamxhr in WebKit and Android browser 2 and 3 and sse in Webkit and Firefox.

Long polling

The HTTP method GET is used to establish a connection, and applied transports are longpollajax, longpollxdr and longpolljsonp. If the server is going to send data continuously, an additional measure is needed for the browser so as not to lose data.

  • Access-Control-Allow-Origin header should be either * or the value of the Origin request header. - longpollxdr.
  • The content-type header should be set to text/javascript if the transport is longpolljsonp, and for the others, text/plain is fine.
  • If the when parameter is open, the server should complete the request immediately. The purpose of this is to tell the browser that the server is alive. The socket in the browser side fires the open event when the first request completes normally. After the completion, poll request has the when parameter whose value is poll not open.
  • If the when parameter is poll and the server did nothing to the request, completion of this request should be regarded as the end of a connection. So, the socket in the browser side fires the close event if the response is empty and poll if not.

Sending event

A final string to be sent to the browser is a JSON string representing an event object, and the inbound handler in the browser side makes such a raw string into an event object. The event object should contain at least the type property.

{"type":"message","data":"data","id":1,"reply":false}
  • type: An event type.
  • id: An event id.
  • data: Data.
  • reply: Whether to request a reply.

WebSocket

A WebSocket message corresponds to a Portal event. Just send it.

Streaming

The response text should be formatted in the event stream format. This is a requirement of the sse transport, but the rest of the streaming transports also accept that format for convenience. Break data up by \r, \n, or \r\n, append data: to the beginning of each line and \n to the end of each line and print them. Finally, print \n to mark the end of a single data. Android browser 2 and 3 need 4K padding at the top of each event.

Long polling

For the longpollajax and longpollxdr transport, the response text corresponds to a event. In case of the longpolljsonp transport, the response text is a JavaScript code snippet executing a given callback in the browser side with data. The callback function name is passed as the request parameter callback and the data should be escaped to a JavaScript string literal. All the long polling transports has to finish the request after processing.

Receiving event

A JSON string representing an event object is generated by outbound handler in the browser side and sent to the server.

{"id":1,"socket":"341043d0-5564-4cdd-bb25-64dbe40b7a71","type":"message","data":"data","reply":false}
  • id: An event id.
  • socket: A socket id.
  • type: An event type.
  • data: Data.
  • reply: Whether to request a reply.

WebSocket

A WebSocket message corresponds to a Portal event. Just receive it.

HTTP transport

For transports based on http protocol like streaming and long polling, the HTTP method POST is used to receive event. The POST request message body is like the following.

data={"id":1,"socket":"0c9d84f2-b8e3-4d65-bf41-7bb32f597b74","type":"message","data":"data","reply":false}
  • The character encoding should be set to UTF-8 explicitly.
  • The server has to access and parse the request’s message body directly, because to generalize how to extract data, the socket sets content type to text/plain not application/x-www-form-urlencoded. Nevertheless, XDomainRequest doesn’t set content type header explicitly in a cross-origin connection. The problem results from the fourth restriction of the XDomainRequest.
  • The real data which the browser sends is a substring of the body which begins after the data= and extends to the end of the body. For your information, XDomainRequest doesn’t send body after unloading event.

Advanced

The following topics are not essential for two-way communication, but provide additional useful functions which makes the application more solid.

Retrieving lost event

If the transport is long polling and the server sends event during the idle time where the browser can’t receive events, those events could be vaporized. To help make up for lost event, every poll request has the lastEventIds parameter which is a string concatenated by comma and contains event ids the socket in the browser side has received in the previous request’s response.

  • If the transport is long polling, store an event to the cache when sending it.
  • When the next poll request comes, remove events from the cache whose id is included in lastEventIds parameter.
  • If the cache is not empty, make it JSON array and send it.

Heartbeat

The heartbeat communication can resolve a state inconsistency problem which is a case that either of the server or the browser can’t recognize disconnection. The heartbeat event is used. If the request parameter heartbeat is in number format, the socket in the browser side continuously sends this event each specified time so the server should proceed according to the following instructions:

  • Assign an integer greater than 5000 to the heartbeat option in the browser side.
  • Set a heartbeat timer in the server side that closes the connection after the heartbeat interval if the value is number.
  • When the browser sends a heartbeat event, reset the timer and send back the event. If the server can’t respond in 5000ms, the socket in the browser side will regard that the server dies and fire the close event.

Detecting disconnection

Although the heartbeat ensures the state synchronization regardless of the transport and the server, it takes a few seconds. Essentialy, this problem arises only with disconnection of transports based on http protocol, and instant detection can be possible by enabling the notifyAbort option and processing abort request.

  • Set the notifyAbort option to true.
  • If a request parameter when is abort, close the corresponding socket.

Reply

The reply event is a special event which is used to deliver the counterpart’s reply. When the server deals with browser-sent event if the value of the reply property of event object is true, a reply event should be sent. The reply event’s data must contain the id property which is the event id the browser sent and can contain the data and exception properties. Then, done callback if exception is false or fail callback if it’s true in the browser-side will be executed with the attached data.

Setting reply

The server, in common with the socket object in the browser-side, can set a reply callback to the socket object.

  • Increment an event id, every time the server sends an event.
  • Set a reply property of an event object to true if the callback is provided.
  • Client sent reply event is the same with what the server creates. Execute the corresponding callback with proper value on the reply event.