[whatwg] Issues with Web Sockets API

Michael Nordman michaeln at google.com
Tue Jul 7 13:48:03 PDT 2009


On Mon, Jul 6, 2009 at 9:30 PM, Ian Hickson <ian at hixie.ch> wrote:

> On Fri, 26 Jun 2009, James Robinson wrote:
> >
> > 0) postMessage() looks as if it is intended to mimic
> > MessagePort.postMessage(), but the arguments and error conditions are
> > different.  While it would be conceptually nice to treat a web socket in
> > the same way as a message port, it's not possible to treat the two
> > postMessage() functions in the same way.  I'd recommend the WebSocket
> > version be renamed to something like "send()" to avoid confusion and
> > false expectations.
>
> Fair enough. Done.
>
>
>
> > There's similar oddness with receiving events that satisfy the
> MessageEvent
> > interface - since all fields except 'data' will necessarily be invalid I
> > don't see the value in receiving something more complex.
>
> I would like to avoid introducing four different event types for the four
> different types of 'message' events being introduced, which is why I
> overloaded the same interface for all four. I don't think it's a problem.
>
>
> > 1) The 'readyState' attribute can never actually be used by an
> application
> > and is redundant.
> >
> > Initially, the 'readyState' attribute is set to CONNECTING, but while
> > the object is in this state the user is not permitted to interact with
> > the WebSocket in any way.  The only useful thing that a user could do is
> > set event handlers and wait for the 'open' event to fire.  When the
> > WebSocket becomes connected, the readyState becomes 1 and the 'open'
> > event is fired. Once the WebSocket is open, the spec states that
> > whenever the connection is closed the readyState changes to CLOSED and a
> > 'close' event is enqueued. However, users can't usefully check the
> > readyState to see if the WebSocket is still open because there are not
> > and cannot be any synchronization guarantees about when the WebSocket
> > may close.  A user will have to wrap all calls to postMessage() (or
> > send() if the function is renamed) in a try/catch block in order to
> > handle INVALID_STATE_ERRs.  Once the 'close' event has been received the
> > readyState attribute is useless since the state of the WebSocket is
> > known and can never change.
> >
> > I think 'readyState' should just go away since an application will have
> > to keep track of state updates through the fired events and use
> > try/catch blocks around all API calls anyway.
>
> The attribute is mostly present for debugging purposes. I wouldn't expect
> anyone to actually use it for production work.
>
>
> On Fri, 26 Jun 2009, Drew Wilson wrote:
> >
> > Yes, but the "closed" state of a given WebSocket doesn't have to exactly
> > match the state of the underlying TCP connection, in the same way that
> > document.cookies doesn't exactly match the current set of cookies that
> > the network stack may be tracking (they can differ when HTTP responses
> > are received in the background while JS is executing).
> >
> > So if the remote server closes the TCP connection, it generates a
> > "close" event which marks the WebSocket as closed. It means that you
> > could have a situation where you post messages to a WebSocket which
> > aren't received by the server because the connection is closed, but
> > that's true regardless due to the asynchronous nature of the networking
> > protocol.
>
> I've changed the spec to not throw an exception on send() if the
> connection is closed.
>
>
> On Fri, 26 Jun 2009, Kelly Norton wrote:
> >
> > One thing about postMessage that I'm curious about. Since it has to
> > report failure synchronously by throwing an INVALID_STATE_ERR, that
> > seems to imply that all data must be written to a socket before
> > returning and cannot be asynchronously delivered to an I/O thread
> > without adding some risk of silently dropping messages. Seems like the
> > right choice would be to allow outbound messages to drop, which would
> > mean that developers would be forced to do their own handshaking.
>
> send() doesn't report I/O errors, it only throws an exception if the
> connection isn't open yet (and previously, if the connection had died
> prior to it being called, though that is no longer the case), or if the
> input is invalid.
>
>
> > I'm also not sure there is good coverage of error conditions in the
> > spec. The only methods of error notification are exceptions in
> > postMessage and onclose.
>
> In fact, only onclose actually reports an error; the exception from send()
> now only reports a misuse of the API, not a network error.
>
>
> > I had assumed that a WebSocket that fails to connect would invoke
> > onclose asynchronously, but I didn't see that in the spec.
>
> It's there, though subtle. :-)
>
> The constructor in the API spec invokes the "Establish a Web Socket
> connection" algorithm from the protocol spec. That algorithm then invokes
> the "fail the Web Socket connection" algorithm upon failure, and that
> algorithm says to invoke the "close the Web Socket connection" algorithm,
> and that algorithm says that this means that "Web Socket connection is
> closed", and the API spec says "When the Web Socket connection is closed,
> the readyState attribute's value must be changed to CLOSED (2), and the
> user agent must queue a task to fire a simple event called close at the
> WebSocket object".
>
> I've added a note that says this.
>
>
> > Without that you don't even have the ability to know if a
> > socket failed to establish a connection (short of readyState polling).
> > The spec also doesn't indicate that the readyState should transition to
> > CLOSED on connection failure.
>
> This is part of the same sequence of events as described above.
>
>
> On Fri, 26 Jun 2009, Kelly Norton wrote:
> >
> > Doesn't it seem strange that disconnect() causes an onclose event to be
> > dispatched? Should the method not be close() to be consistent with
> > open(), onopen, onclose?
>
> I've renamed disconnect() to close() in both EventSource and WebSocket.
>
>
> On Fri, 26 Jun 2009, Michael Nordman wrote:
> >
> > Does disconnect() attempt to flush pending messages or drop them? There
> > isn't a way to determine if the WebSocket is successfully sending the
> > postMessage data? For all the caller knows, its just backing up and not
> > going anywhere.
> >
> > Something that might add value is an onmessagesent event that fires
> > after a postMessage has put the bits on the wire.
>
> If you want acknowledgements, implement app-level acks -- in practice,
> there's not much difference between hitting the network or not, if the
> other side hasn't yet received the packets.
>
>
> > postMessage() may want another exception condition... 'too much data
> > pending exception'... consider calling postMessage in a while(true)
> > loop... at some point the system is going to have to give up queing the
> > data if its not actually making its way out on the wire.
>
> The spec doesn't specify how UAs are to handle hitting hardware
> limitations or system limitations, because it's often difficult to truly
> control how those cases are handled.
>
>
> On Fri, 26 Jun 2009, James Robinson wrote:
> >
> > Not changing variables out from under executing JavaScript makes a lot
> > of sense, but if that was the case then it's not clear when the
> > readyState could be updated.  The spec states "When the *Web Socket
> > connection is closed*, the readyState attribute's value must be changed
> > to CLOSED (2), and the user agent must queue a task to fire a simple
> > event called close at the WebSocket object." If the browser cannot
> > mutate the readyState until JavaScript stops running then it would
> > either have to either enqueue a second task to change readyState at some
> > point in the future or set the readyState right before dispatching the
> > 'close' event.  The latter would be much nicer to implement - but then
> > it does make the readyState completely useless as it would always be
> > exactly equivalent to the last event that was fired on a given
> > WebSocket.
>
> I've left it as is (the attribute changes on the fly), which is possibly
> risky, but more consistent with how such attributes are handled in
> general.
>
>
> > I think a better way to do error handling is to have an asynchronous
> > onerror callback or event when the browser notes that a message did not
> > make it to the other side.
>
> The client can't really always know this anyway. I think it's better to do
> app-level acking if you care enough.
>
>
> On Fri, 26 Jun 2009, James Robinson wrote:
> >
> > The concept of a port being in a closed state is not very well defined -
> > if the state means only the readyState status, then when can the state
> > legally be updated?  If it has some meaning closer to the state of the
> > underlying connection, then it can't be queried synchronously without
> > very expensive synching to the I/O thread or process.
> >
> > Forcing applications to build their own send/ack functionality would be
> > pretty tragic considering that WebSockets are built on top of TCP.
>
> If we had access to the underlying TCP packets, I guess we could return a
> number with each send() and have some way to query the number of the
> mesage that the most recent packet that got all the way to other side
> contained, but in practice I don't think that implementations are always
> going to have access to that, and also it's not just that the other stack
> got the message that matters, but that the remote server actually got the
> messages and processed it.
>
>
> On Fri, 26 Jun 2009, Michael Nordman wrote:
> >
> > If you're uploading a large data set incrementally across many distinct
> > postMessage calls (perhaps to leave room for other control messages
> > interspersed amoungst them, or to present progress info), how do you
> > know when to queue more data to be sent.
>
> I think when we add support for file upload, we'll make it so that it
> automagically supports this case. That is, you'll say "upload this file in
> small bits" and then if you later say "send this text message", the text
> message will be sent before any pending file bits. We can use a separate
> type of packet in the WebSocket stream to do this.


Sounds like that would require a protocol change. Is the message framing
spec'd in such a way that a new 'packet type' can be introduced in a
backward compatible fashion?


>
>
> --
> Ian Hickson               U+1047E                )\._.,--....,'``.    fL
> http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
> Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20090707/28a4fe64/attachment-0001.htm>


More information about the whatwg mailing list