Initial web socket API.

This PR is to a `websocket` feature branch for later merging into `master`.
nit: I think it might be a mistake to say that a connection is closed after a network error has occurred. Ie. even when the network breaks (timeout, etc.) the resource still needs to be closed. Ie. everything needs to be closed _locally_ by the client, even if it was already closed by the remote peer.

You get an IOException if you interact with something that's finished remotely (not your fault) and an IllegalStateException if you interact with something that's closed locally (a programming error).