Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
This API provides interfaces to raw UDP sockets, TCP Client sockets and TCP Server sockets.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
The short name for this API has been changed from raw-sockets to tcp-udp-sockets as a more accurate description of its scope.
This document was published by the System Applications Working Group as an updated Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-sysapps@w3.org (subscribe, archives). All feedback is welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 14 October 2005 W3C Process Document.
This specification is based the Streams API, [STREAMS]. Note that the Streams API is work in progress and any changes made to Streams may impact the TCP and UDP Socket API specification. However, it is the editor's ambition to continously update the TCP and UDP API specification to be aligned with the latest version the Streams API.
This is a note on error handling.
When using promises rejection reasons should always be instances of the ECMAScript Error type such as DOMException or the built in ECMAScript error types. See Promise rejection reasons. In the TCP and UDP Socket API the error names defined in WebIDL Exceptions are used. If additional error names are needed an update to Github WebIDL should be requested through a Pull Request.
This is a note on data types of TCP and UDP to send and receive.
In the previous version of this API the send() method accepted the following data types for the data to send: DOMString,Blob, ArrayBuffer or ArrayBufferView. This was aligned with the send() method for Web Sockets. In this Streams API based version only ArrayBuffer is accepted as type for data to send. The reason is that encoding issues in a Streams based API should instead be handled by a transform stream.
This section is non-normative.
Use this API to send and receive data over the network using TCP or UDP.
Examples of use cases for this API are:
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key word MUST is to be interpreted as described in [RFC2119].
This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.
Implementations that use ECMAScript to implement the APIs defined in this specification MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [WEBIDL], as this specification uses that specification and terminology.
The Promise
interface provides asynchronous access to the result of an operation
that is ongoing, has yet to start, or has completed, as defined in
[ES6].
This API must be only exposed to trusted content.
There is ongoing work on trust and permissions in W3C. For example see Workshop on trust and permissions for Web applications 3–4 September 2014, Paris, France. The assumption is that this API must only be exposed to trusted content according to a security model based on existing web security mechanisms such as tls/ssl, signed manifests, csp, etc. The details of that security model as such is out of scope for this specification as this model should apply to any security and privacy sensitive API.
UDPSocket
The UDPSocket
interface defines attributes and methods for
UDP communication
// // This example shows a simple implementation of UPnP-SSDP M-SEARCH // discovery using a multicast UDPSocket // var address = '239.255.255.250', port = '1900', serviceType = 'upnp:rootdevice', rn = '\r\n', search = ''; // Create a new UDP client socket var mySocket = new UDPSocket(); // Build an SSDP M-SEARCH multicast message search += 'M-SEARCH * HTTP/1.1' + rn; search += 'ST: ' + serviceType + rn; search += 'MAN: "ssdp:discover"' + rn; search += 'HOST: ' + address + ':' + port + rn; search += 'MX: 10'; // Receive and log SSDP M-SEARCH response messages function receiveMSearchResponses() { // While data in buffer, read and log UDP message while (mySocket.readable.state === "readable") { var msg = mySocket.readable.read(); console.log ('Remote address: ' + msg.remoteAddress + ' Remote port: ' + msg.remotePort + 'Message: ' + ab2str(msg.data)); // ArrayBuffer to string conversion could also be done by piping // through a transform stream. To be updated when the Streams API // specification has been stabilized on this point. } // Wait for SSDP M-SEARCH responses to arrive mySocket.readable.wait().then( receiveMSearchResponses, e => console.error("Receiving error: ", e); ); } // Join SSDP multicast group mySocket.joinMulticast(address); // Send SSDP M-SEARCH multicast message mySocket.writeable.write( {data : str2ab(search), remoteAddress : address, remotePort : port }).then( () => { // Data sent sucessfully, wait for response console.log('M-SEARCH Sent'); receiveMSearchResponses(); }, e => console.error("Sending error: ", e); ); // Log result of UDP socket setup. mySocket.opened.then( () => { console.log("UDP socket created sucessfully"); }, e =>console.error("UDP socket setup failed due to error: ", e); ); // Handle UDP socket closed, either as a result of the application // calling mySocket.close() or an error causing the socket to be closed. mySocket.closed.then( () => { console.log("Socket has been cleanly closed"); }, e => console.error("Socket closed due to error: ", e); );
[Constructor (optional UDPOptions options)]
interface UDPSocket {
readonly attribute DOMString? localAddress;
readonly attribute unsigned short? localPort;
readonly attribute DOMString? remoteAddress;
readonly attribute unsigned short? remotePort;
readonly attribute boolean addressReuse;
readonly attribute boolean loopback;
readonly attribute SocketReadyState
readyState;
readonly attribute Promise opened;
readonly attribute Promise closed;
readonly attribute ReadableStream readable;
readonly attribute WriteableStream writeable;
Promise close ();
void joinMulticast (DOMString multicastGroupAddress);
void leaveMulticast (DOMString multicastGroupAddress);
};
addressReuse
of type boolean, readonly true
allows the socket to be bound to a local address/port
pair that already is in use. Can be set by the options
argument in the constructor. Default is true
.closed
of type Promise, readonly close()
) or
through an error situation, e.g. network contact lost.
Returns the closedPromise
that was created
in the UDPSocket
constructor.
localAddress
of type DOMString, readonly , nullableoptions
argument's localAddress
member. If
this member is not present but the remoteAddress
member is
present, the user agent binds the socket to a local IPv4/6 address
based on the routing table and possiby a preselect default local
interface to use for the selected remoteAddress
. Else,
i.e. neither the localAddress
or the
remoteAddress
members are present in the constructor's
options
argument, the localAddress
attribute is set to null
.localPort
of type unsigned short, readonly , nullableoptions
argument in the constructor. If not set the
user agent binds the socket to an ephemeral local port decided by
the system and this attribute is null. loopback
of type boolean, readonly true
means that sent
multicast data is looped back to the sender.
Can be set by the options
argument in the constructor.
Default is false
.opened
of type Promise, readonly openedPromise
that was created in the
UDPSocket
constructor.
readable
of type ReadableStream, readonly readyState
of type SocketReadyState
, readonly SocketReadyState
for details. remoteAddress
of type DOMString, readonly , nullableremotePort
of type unsigned short, readonly , nullablewriteable
of type WriteableStream, readonly close
Closes the UDP socket. Returns the closedPromise
that
was created in the UDPSocket
constructor.
Promise
joinMulticast
Joins a multicast group identified by the given address.
Note that even if the socket is only sending to a multicast address, it is a good practice to explicitely join the multicast group (otherwise some routers may not relay packets).
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
multicastGroupAddress | DOMString | ✘ | ✘ | The multicast group address. |
void
leaveMulticast
Leaves a multicast group membership identified by the given address.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
multicastGroupAddress | DOMString | ✘ | ✘ | The multicast group address. |
void
When the UDPSocket
constructor is invoked, the User Agent
MUST run the following steps:
mySocket
").
options
argument's remoteAddress
member is present and it is a valid host name or IPv4/6 address
then set the mySocket.remoteAddress
attribute
(default remote address) to the requested address. Else, if the
remoteAddress
member is present but it is not a
valid host name or IPv4/6 address then throw DOMException
InvalidAccessError
and abort the remaining
steps.
Otherwise, if the options
argument's remoteAddress
member is absent then set the mySocket.remoteAddress
attribute (default remote address) to null
.
options
argument's remotePort
member
is present and it is a valid port number then set the
mySocket.remotePort
attribute (default remote port)
to the requested port. Else, if the remotePort
member
is present but it is not a valid port number then throw DOMException
InvalidAccessError
and abort the remaining steps.
Otherwise, if the options
argument's remotePort
member is absent then set the mySocket.remotePort
attribute (default port number) to null
.
options
argument's localAddress
member is present and the options
argument's
remoteAddress
member is present, execute the following
step:
options
argument's localAddress
member is a valid IPv4/6 address for a local interface that can
be used to connect to the selected remoteAddress
(according to the routing table) bind the socket to this local
IPv4/6 address and set the mySocket.localAddress
attribute to this addres. Else, if the localAddress
member is present but it is not a valid local IPv4/6 address
for a local interface that can be used to connect to the
selected remoteAddress
, throw DOMException
InvalidAccessError
and abort the remaining
steps.
options
argument's localAddress
member is present and the options
argument's
remoteAddress
member is absent, execute the following
step:
options
argument's localAddress
member is a valid IPv4/6 address for a local interface on the
device bind the socket to this local IPv4/6 address and set the
mySocket.localAddress
attribute to this addres.
Else, if the localAddress
member is present but
it is not a valid local IPv4/6 address for a local interface
on the device, throw DOMException InvalidAccessError
and abort the remaining steps. Note that binding the UDPSocket
to a certain local interface means that the socket can only be
used to send UDP datagrams to peers reachable through this
local interface.
options
argument's localAddress
member is absent, and the options
argument's
remoteAddress
member is present, execute the following
steps:
remoteAddress
. If no local interface can be used
to send datagrams to the selected remoteAddress
,
throw DOMException InvalidAccessError
and
abort the remaining steps.
remoteAddress
bind the socket to the IPv4/6 address
of the "default" local interface to use for the selected
remoteAddress
. The selection of a "default" local
interface is out of scope for this specification.
mySocket.localAddress
attribute to the
local address that the socket is bound to.
options
argument's localAddress
member is absent, and the options
argument's
remoteAddress
member is absent, execute the following
step:
mySocket.localAddress
attribute to
null
.
options
argument's localPort
member
is absent then bind the socket to an ephemeral local port decided
by the system and set the mySocket.localPort
attribute
to null.
Otherwise, bind the socket to the requested local port and set the
mySocket.localPort
attribute to the local port that
the socket is bound to.
mySocket.addressReuse
attribute to the value
of the options
argument's addressReuse
member if it is present or to true
if the options
argument's addressReuse
member is not present.
options
argument's loopback
member
is present then set the mySocket.loopback
attribute
to the value of this field. Else set this attribute to false
.
mySocket.readyState
attribute to "opening".
openedPromise
", and store
it so it can later be returned by the opened
property.
closedPromise
", and store
it so it can later be returned by the closed
property and the close
method.
mySocket.readable
attribute be a new
ReadableStream object, [STREAMS]. The User Agent MUST implement
the adaptation layer to [STREAMS] for this new ReadableStream
object through implementation of a number of functions that are
given as input arguments to the constructor and called by the
[STREAMS] implementation. The semantics for these
functions are described below:
start()
function is called
immediately by the [STREAMS] implementation.
The start()
function MUST run the following steps:
openedPromise
.
mySocket.readyState
attribute's value to "open".
openedPromise
with
undefined
.
start()
function
and MUST be called by the start()
function
implementation according to the following steps:
enqueue()
argument of start()
is a function that pushes received data into the
internal buffer. UDPMessage
.
UDPMessage
object's
data
member to a new read-only
ArrayBuffer
object whose contents
are the received UDP datagram [TYPED-ARRAYS].
remoteAddress
member of
the UDPMessage
object to the source
address of the received UDP datagram.
remotePort
member of the
UDPMessage
object to the source port
of the received UDP datagram.
enqueue()
to push the
UDPMessage
object into the internal
[STREAMS] receive buffer.
Note that enqueue()
returns false if
the high watermark of the buffer is reached.
However, as there is no flow control mechanism
in UDP the flow of datagrams can't be stopped.
The enqueue()
return value should
therefore be ignored. This means that datagrams
will be lost if the internal receive buffer
has been filled to it's memory limit but
this is the nature of an unreliable protocol
as UDP.
error()
argument of start()
is a function that handles readable stream errors and
closes the readble stream.mySocket.readyState
is "opening")
has failed, e.g. because the local address/port pair is
already in use and mySocket.addressReuse
is false
, the following steps MUST run:
error()
with DOMException
"NetworkError"
.
openedPromise
with DOMException
"NetworkError"
.
closedPromise
with DOMException
"NetworkError"
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this socket.
mySocket.readyState
is "open"), e.g. network connection is lost, the
following steps MUST run:
error()
with DOMException
"NetworkError"
.
closedPromise
with
DOMException "NetworkError"
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this
socket.
ArrayBuffer
,
[TYPED-ARRAYS], the following steps MUST run:
error()
with TypeError
.
closedPromise
with
TypeError
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this
socket.
pull()
function MUST be omitted
as there is no flow control mechanism in UDP and the flow
of datagrams cannot be stopped and started again.
cancel()
function input
argument is called by the [STREAMS] implementation when
the ReadbleStream should be canceled. For UDP this means that
the UDP socket should be closed for reading and writing.
The cancel()
function MUST run the following steps:
mySocket.readyState
is "closed" then
do nothing and abort the remaning steps.
mySocket.readyState
is "opening"
then fail the UDP socket setup process, reject openedPromise
with DOMException AbortError
and set the
mySocket.readyState
attribute to "closed".
mySocket.readyState
is "open" the the
following steps MUST run:
mySocket.writeable.close()
to
assure that any buffered send data is sent.
mySocket.readyState
attribute's value to "closed".
closedPromise
with
undefined
and release any
underlying resources associated with this
socket.
If the constructor's strategy
argument is
omitted the
Default strategy for Readable Streams
applies. Currently this means that the ReadableStream
object goes to "readable" state after 1 chunk has been
enqueued to the internal ReadableStream object's input
buffer. An application should call .wait() to be notified
when the state changes to "readable". To be further
investigated which ReadableStreamStrategy that should
be applied to UDP.
mySocket.writeable
attribute be a new
WritableStream object, [STREAMS]. The User Agent MUST implement
the adaptation layer to [STREAMS] for this new WritableStream
object through implementation of a number of functions that are
given as input arguments to the constructor and called by the
[STREAMS] implementation. The semantics for these
functions are described below:
start()
function MUST run the
following steps:
writableStartPromise
".
mySocket.readable
attribute constructor's start()
function )
succeded resolve writableStartPromise
with undefined
, else reject writableStartPromise
with DOMException "NetworkError"
.
write(chunk)
function is called by the [STREAMS] implementation to
write UDP data. The write()
function MUST run the following steps:
writePromise
"
chunk
argument to a
UDPMessage
object (per [WEBIDL] dictionary
conversion).
options
argument's
remoteAddress
member and the
UDPMessage
object's remoteAddress
member is not present or null then throw DOMException
InvalidAccessError
and abort these steps.
options
argument's
remotePort
member and the
UDPMessage
object's remotePort
member is not present or null then throw DOMException
InvalidAccessError
and abort these steps.
data
member of the UDPMessage
object. The destination
address is the address defined by the
UDPMesssage object's remoteAddress
member if present, else the destination address
is defined by the UDPSocket's constructor
options
argument's
remoteAddress
member. The destination
port is the port defined by the
UDPMesssage object's remotePort
member if present, else the destination port
is defined by the UDPSocket's constructor
options
argument's
remotePort
member.
writePromise
with undefined
, else reject
writePromise
with DOMException
"NetworkError"
.
close()
and abort()
functions MUST be omitted as it is not possible to just close
the writable side of a UDP socket.
If the constructor's strategy
argument is
omitted the
Default strategy for Writable Streams
applies. Currently this means that the WriteableStream
object goes to "waiting" state after 1 chunk has been
written to the internal WriteableStream object's output
buffer. This means that the application should call .wait()
to be notified of when the state changes to "writable",
i.e. the queued chunk has been written to the remote peer
and more data chunks could be written. To be further
investigated which WritableStreamStrategy that should
be applied to UDP.
UDPSocket
object ("mySocket
")
to the application.
The close
method when invoked MUST run the
following steps:
closedPromise
.
TCPSocket
The TCPSocket
interface defines attributes and methods for TCP
communication
// // This example shows a simple TCP echo client. // The client will send "Hello World" to the server on port 6789 and log // what has been received from the server. // // Create a new TCP client socket and connect to remote host var mySocket = new TCPSocket("127.0.0.1", 6789); // Send data to server mySocket.writeable.write("Hello World").then( () => { // Data sent sucessfully, wait for response console.log("Data has been sent to server"); mySocket.readable.wait().then( () => { // Data in buffer, read it console.log("Data received from server:" + mySocket.readable.read()); // Close the TCP connection mySocket.close(); }, e => console.error("Receiving error: ", e); ); }, e => console.error("Sending error: ", e); ); // Signal that we won't be writing any more and can close the write half of the connection. mySocket.halfClose(); // Log result of TCP connection attempt. mySocket.opened.then( () => { console.log("TCP connection established sucessfully"); }, e =>console.error("TCP connection setup failed due to error: ", e); ); // Handle TCP connection closed, either as a result of the application // calling mySocket.close() or the other side closed the TCP // connection or an error causing the TCP connection to be closed. mySocket.closed.then( () => { console.log("TCP socket has been cleanly closed"); }, e => console.error("TCP socket closed due to error: ", e); );
[Constructor (DOMString remoteAddress, unsigned short remotePort,
optional TCPOptions options)]
interface TCPSocket {
readonly attribute DOMString remoteAddress;
readonly attribute unsigned short remotePort;
readonly attribute DOMString localAddress;
readonly attribute unsigned short localPort;
readonly attribute boolean addressReuse;
readonly attribute boolean noDelay;
readonly attribute SocketReadyState
readyState;
readonly attribute Promise opened;
readonly attribute Promise closed;
readonly attribute ReadableStream readable;
readonly attribute WriteableStream writeable;
Promise close ();
void halfClose ();
};
addressReuse
of type boolean, readonly true
allows the socket to be bound to a local address/port
pair that already is in use. Can be set by the options
argument in the constructor. Default is true
.closed
of type Promise, readonly close()
) or through an error situation.
Returns the closedPromise
that was created
in the TCPSocket
constructor.
localAddress
of type DOMString, readonly options
argument in the constructor. If not set the user agent
binds the socket to an IPv4/6 address based on the routing table and
possibly a preselect default local interface to use for the selected
remoteAddress
. localPort
of type unsigned short, readonly options
argument in the constructor. If not set the
user agent binds the socket to an ephemeral local port decided by
the system. noDelay
of type boolean, readonly true
if the Nagle algorithm for send coalescing,
[NAGLE], is disabled. Can be set by the
options
argument in the constructor. Default is
true
.opened
of type Promise, readonly openedPromise
that was created
in the TCPSocket
constructor.
readable
of type ReadableStream, readonly readyState
of type SocketReadyState
, readonly SocketReadyState
for
details.remoteAddress
of type DOMString, readonly remotePort
of type unsigned short, readonly writeable
of type WriteableStream, readonly close
Closes the TCP socket. Returns the closedPromise
that
was created in the TCPSocket
constructor.
Promise
halfClose
Half closes the TCP socket.
void
When the TCPSocket
constructor is invoked, the User Agent MUST
run the following steps:
mySocket
").
remoteAddress
argument is not a valid host name
or IPv4/6 address and/or the remotePort
argument is
not a valid port number then throw DOMException "InvalidAccessError"
and abort the remaining steps, else set the mySocket.remoteAddress
and mySocket.remotePort
attributes to the requested values.
options
argument's localAddress
member is present and it is a valid IPv4/6 address for a local
interface that can be used to connect to the selected
remoteAddress
(according to the routing table) bind the
socket to this local IPv4/6 address and set the mySocket.localAddress
attribute to this addres. Else, if the localAddress
member is present but it is not a valid local IPv4/6 address for a
local interface that can be used to connect to the selected
remoteAddress
then throw DOMException
"InvalidAccessError"
and abort the remaining steps.options
argument's localAddress
member is absent, execute the following steps:
remoteAddress
.
If no local interface can be used to connect to the selected
remoteAddress
then throw DOMException
"InvalidAccessError"
and abort the remaining
steps.
remoteAddress
bind the socket to the IPv4/6 address of the "default" local
interface to use for the selected remoteAddress
.
The selection of a "default" local interface is out of scope
for this specification.
mySocket.localAddress
attribute to the
local address that the socket is bound to.
options
argument's localPort
member
is absent then bind the socket to an ephemeral local port decided
by the system and set the mySocket.localPort
attribute
to this port.
Otherwise, bind the socket to the requested local port and set the
mySocket.localPort
attribute to the local port that
the socket is bound to.
mySocket.addressReuse
attribute to the value
of the options
argument's addressReuse
member if it is present or to true
if the options
argument's addressReuse
member is not present.
mySocket.noDelay
attribute to the value of
the options
argument's noDelay
member
if it is present or to true
if the options
argument's noDelay
member is not present.
mySocket.readyState
attribute to "opening".
openedPromise
", and store
it so it can later be returned by the opened
property.
closedPromise
", and store
it so it can later be returned by the closed
property and the close
method.
mySocket.readable
attribute be a new
ReadableStream object, [STREAMS]. The User Agent MUST implement
the adaptation layer to [STREAMS] for this new ReadableStream
object through implementation of a number of functions that are
given as input arguments to the constructor and called by the
[STREAMS] implementation. The semantics for these
functions are described below:
start()
function is called
immediately by the [STREAMS] implementation.
The start()
function MUST run the following steps:
openedPromise
.
mySocket.readyState
attribute's value to
"open".
openedPromise
with undefined
.
start()
function and MUST be called by the
start()
function implementation according to the
following steps:
enqueue()
argument of start()
is a function that pushes received data into the
internal buffer. ArrayBuffer
object whose contents are the received TCP data.
enqueue()
to push the
ArrayBuffer
into the internal
[STREAMS] receive buffer.
enqueue()
returns false and the TCP
flow control MUST be used to stop the data
transmission from the remote peer.
close()
argument of start()
is a function that closes the readable stream.close()
)
through a successful TCP connection closing handshake
the following steps MUST run:
close()
.
mySocket.readyState
attribute's
value to "closed" and release any
underlying resources associated with this socket.
closedPromise
with
undefined
.
error()
argument of start()
is a function that handles readable stream errors and
closes the readble stream.mySocket.readyState
is "opening") has
failed the following steps MUST run:
error()
with DOMException
"NetworkError"
.
openedPromise
with DOMException
"NetworkError"
.
closedPromise
with DOMException
"NetworkError"
.
mySocket.readyState
attribute's value
to "closed" and release any underlying resources
associated with this socket.
mySocket.readyState
is "open") has been lost
the following steps MUST run:
error()
with DOMException
"NetworkError"
.
closedPromise
with DOMException
"NetworkError"
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this
socket.
mySocket.readyState
is "closing")
has failed the following steps MUST run:
error()
with DOMException
"NetworkError"
.
closedPromise
with DOMException
"NetworkError"
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this socket.
ArrayBuffer
,
[TYPED-ARRAYS], the following steps MUST run:
error()
with TypeError
.
closedPromise
with
TypeError
.
mySocket.readyState
attribute's value to "closed" and release any
underlying resources associated with this socket.
pull()
function is called
by the [STREAMS] implementation if the internal buffer
has been emptied, but the stream's consumer still wants more
data.
The pull()
function MUST run the following steps:
cancel()
function input
argument is called by the [STREAMS] implementation when
the ReadbleStream should be canceled. For TCP this means that
the TCP connection should be terminated.
The cancel()
function MUST run the following steps:
mySocket.readyState
is "closing" or "closed" then
do nothing and abort the remaning steps.
mySocket.readyState
is "opening" then fail the
connection attempt, reject openedPromise
and
closedPromise
with DOMException
AbortError
and set the mySocket.readyState
attribute to "closing".
mySocket.readyState
is "open" then the
following steps MUST run:
mySocket.writeable.close()
to
assure that any buffered send data is sent
before closing the socket.
mySocket.readyState
attribute's value to "closing".
If the constructor's strategy
argument is
omitted the
Default strategy for Readable Streams
applies. Currently this means that the ReadableStream
object goes to "readable" state after 1 chunk has been
enqueued to the internal ReadableStream object's input
buffer. An application should call .wait() to be notified
when the state changes to "readable". To be further
investigated which ReadableStreamStrategy that should
be applied to TCP.
mySocket.writeable
attribute be a new
WritableStream object, [STREAMS]. The User Agent MUST implement
the adaptation layer to [STREAMS] for this new WritableStream
object through implementation of a number of functions that are
given as input arguments to the constructor and called by the
[STREAMS] implementation. The semantics for these
functions are described below:
start()
function MUST run the
following steps:
writableStartPromise
".
mySocket.readable
attribute
constructor's start()
function ) succeded
resolve writableStartPromise
with undefined
, else reject
writableStartPromise
with DOMException
"NetworkError"
.
write(chunk)
function is
called by the [STREAMS] implementation to write data to
the remote peer on the TCP connection.
The write()
function MUST run the following steps:
writePromise
"
chunk
parameter to the address and port of the recipient as
stated by the TCPSocket object constructor's
remoteAddress
and remotePort
fields. The data in the chunk
parameter
can be of any type.
writePromise
with undefined
, else reject
writePromise
with DOMException
"NetworkError"
.
close()
function is called
by the [STREAMS] implementation to close the writable
side of the connection, that is a TCP "half close" is
performed. The close()
function MUST run the
following steps:
mySocket.readyState
is "closing" or "closed" then
do nothing.
mySocket.readyState
is "opening" then complete
the connection attempt. If succesful send FIN and set the
mySocket.readyState
attribute to "halfclosed".
mySocket.readyState
is "open" then send FIN and
set the mySocket.readyState
attribute to "halfclosed".
close()
after all queued-up writes successfully completed.
abort()
function is called
by the [STREAMS] implementation to abort the writable
side of the connection. This function MUST run the same steps
as close()
but note that the Streams
implementation will throw away any pending queued up chunks.
If the constructor's strategy
argument is
omitted the
Default strategy for Writable Streams
applies. Currently this means that the WriteableStream
object goes to "waiting" state after 1 chunk has been
written to the internal WriteableStream object's output
buffer. This means that the application should call .wait()
to be notified of when the state changes to "writable",
i.e. the queued chunk has been written to the remote peer
and more data chunks could be written. To be further
investigated which WritableStreamStrategy that should
be applied to TCP.
TCPSocket
object ("mySocket
")
to the application.
The close()
method when invoked MUST run the
following steps:
mysocket.readable.cancel(reason)
. (Reason codes TBD.)
closedPromise
.
The halfClose()
method when invoked MUST run the
following steps:
mysocket.writeable.close()
.
TCPServerSocket
The TCPServerSocket
interface supports TCP server sockets that
listens to connection attempts from TCP clients
// // This example shows a simple TCP echo server. // The server will listen on port 6789 and respond back with whatever // has been sent to the server. // // Create a new server socket that listens on port 6789 var myServerSocket = new TCPServerSocket({"localPort": 6789}); // Listen for connection attempts from TCP clients. listenForConnections(); function listenForConnections() { myServerSocket.listen().then( connectedSocket => { // A connection has been accepted console.log ("Connection accepted from address: " + connectedSocket.remoteAddress + " port: " + connectedSocket.remotePort); // Wait for data waitForData (); function waitForData () { connectedSocket.readable.wait().then( () => { // Data in buffer, read it var receivedData = connectedSocket.readable.read(); console.log ("Received: " + receivedData); // Send data back connected.writeable.write(receivedData).then( () => { console.log ("Sending data succeeded"); }, e => console.error("Failed to send: ", e); }, // Continue to wait for data waitForData (); }, e => { console.error("Error in connection: ", e); // Continue to wait for data waitForData (); } ); } // Continue to listen for new connections listenForConnections(); }, e => { console.error("A client connection attempt failed: ", e); // Continue to listen for new connections listenForConnections(); } ); } // Log result of TCP server socket creation attempt. myServerSocket.opened.then( () => { console.log("TCP server socket created sucessfully"); }, e =>console.error("TCP server socket creation failed due to error: ", e); ); // Handle TCP server closed, either as a result of the application // calling myServerSocket.close() or due to an error. myServerSocket.closed.then( () => { console.log("TCP server socket has been cleanly closed"); }, e => console.error("TCP server socket closed due to error: ", e); );
[Constructor (optional TCPServerOptions options)]
interface TCPServerSocket {
readonly attribute DOMString localAddress;
readonly attribute unsigned short localPort;
readonly attribute boolean addressReuse;
readonly attribute SocketReadyState
readyState;
readonly attribute Promise opened;
readonly attribute Promise closed;
Promise listen ();
Promise close ();
};
addressReuse
of type boolean, readonly true
allows the socket to be bound to a local
address/port pair that already is in use. Can be set by the
options
argument in the constructor. Default is
true
.closed
of type Promise, readonly close()
) or through
an error situation. Returns the closedPromise
that
was created in the TCPSocket
constructor.
localAddress
of type DOMString, readonly options
argument in the constructor. If not set the
the server will accept connections directed to any IPv4 address
and this atribute is set to null
.
localPort
of type unsigned short, readonly options
argument in the constructor. If not
set the user agent binds the socket to an ephemeral local port
decided by the system and sets this atribute to null
.
opened
of type Promise, readonly openedPromise
that was created in the
TCPServerSocket
constructor.
readyState
of type SocketReadyState
, readonly SocketReadyState
for details. close
Closes the TCP server socket. If listen()
has been
called the listening for incoming connections is stopped but existing
TCP connections are kept open. Returns the
closedPromise
that was created in the
TCPServerSocket
constructor.
Promise
listen
Listens for incoming connection attempts on the specified port and
address. Returns the connectionPromise
, which is for
a succeful connection resolved with the TCPSocket
object for the accepted TCP connection and rejected with
DOMException "NetworkError"
if there is an error on
an incoming connection attempt.
Promise
When the TCPServerSocket
constructor is invoked, the User Agent
MUST run the following steps:
TCPServerSocket
object ("myServerSocket
").
options
argument's localAddress
member is absent the server will accept connections directed to
any IPv4 address and the localAddress
attribute is
set to null
.
Otherwise, if the requested local address is a valid IPv4/6 address
for a local interface on the device bind the server socket to this
local IPv4/6 address and set the localAddress
attribute to this address. Else, if the localAddress
member is present but it is not a valid local IPv4/6 address for a
local interface on the device, throw DOMException InvalidAccessError
and abort the remaining steps.
options
argument's localPort
member
is absent then bind the socket to an ephemeral local port decided
by the system and set the localPort
attribute to
null
.
Otherwise, bind the socket to the requested local port and
set the localPort
attribute to the local port that the
socket is bound to.
addressReuse
attribute to the value of the
options
argument's addressReuse
member
if it is present or to true
if the options
argument's addressReuse
member is not present.
myServerSocket.readyState
attribute to "opening".
openedPromise
", and store
it so it can later be returned by the opened
property.
closedPromise
", and store
it so it can later be returned by the closed
property and the close
method.
TCPServerSocket
object to the
application.
The close
method when invoked MUST run the
following steps:
myServerSocket.readyState
attribute to "closed".
closedPromise
with
undefined
.
The listen
method when invoked MUST run the
following steps:
myServerSocket.readyState
attribute is"closed" then
throw DOMException "InvalidStateError"
and abort the
remaining steps.
connectionPromise
".
connectionPromise
.
When a new TCP server socket has successfully been created the user agent MUST run the following steps:
myServerSocket.readyState
attribute's value to "open".
openedPromise
with undefined
.
When the attempt to create a new TCP server socket
(myServerSocket.readyState
is "opening") has failed the
user agent MUST run the following steps:
myServerSocket.readyState
attribute's value to
"closed".
openedPromise
with DOMException
"NetworkError"
.
closedPromise
with DOMException
"NetworkError"
.
When there is an error on an established TCP server socket
(myServerSocket.readyState
is "open"), e.g. loss of network
contact, the user agent MUST run the following steps:
myServerSocket.readyState
attribute's value to
"closed".
closedPromise
with DOMException
"NetworkError"
.
Upon a new successful connection to the TCP server socket the user agent MUST run the following steps:
TCPSocket
.
remoteAddress
attribute of socket
to the IPv4/6 address of the peer.
remotePort
attribute of socket
to the source port of the of the peer.
localAddress
attribute of socket
to the used local IPv4/6 address.
localPort
attribute of socket to
the used local source port.
readyState
attribute of socket
to "open".
bufferedAmount
attribute of socket
to 0.
connectionPromise
with socket as
argument.
Upon a new connection attempt to the TCP server socket that can not be served, e.g. due to max number of open connections, the user agent MUST run the following steps:
connectionPromise
with DOMException
"NetworkError"
.
UDPMessage
The UDPMessage
dictionary represents UDP data including
address and port of the remote peer. The field data is mandatory
but remoteAddress and remotePort are optional.
dictionary UDPMessage {
ArrayBuffer data;
DOMString remoteAddress;
unsigned short remotePort;
};
UDPMessage
Membersdata
of type ArrayBufferremoteAddress
of type DOMStringremotePort
of type unsigned shortUDPOptions
States the options for the UDPSocket. An instance of this dictionary can
optionally be used in the constructor of the UDPSocket
object, where
all fields are optional.
dictionary UDPOptions {
DOMString localAddress;
unsigned short localPort;
DOMString remoteAddress;
unsigned short remotePort;
boolean addressReuse;
boolean loopback;
};
UDPOptions
MembersaddressReuse
of type booleantrue
allows the socket to be bound to a local address/port pair that
already is in use. Default is true
.localAddress
of type DOMStringremoteAddress
if this member is present. Else the
UDPSocket is unbound to a local interface. localPort
of type unsigned shortloopback
of type booleantrue
means that sent
multicast data is looped back to the sender.
Default is false
.remoteAddress
of type DOMStringremotePort
of type unsigned shortTCPOptions
States the options for the TCPSocket. An instance of this dictionary can
optionally be used in the constructor of the TCPSocket
object,
where all fields are optional.
dictionary TCPOptions {
DOMString localAddress;
unsigned short localPort;
boolean addressReuse;
boolean noDelay;
boolean useSecureTransport;
};
TCPOptions
MembersaddressReuse
of type booleantrue
allows the socket to be bound to a local
address/port pair that already is in use. Default is true
.
localAddress
of type DOMStringremoteAddress
. localPort
of type unsigned shortnoDelay
of type booleantrue
if the Nagle algorithm for send coalescing,
[NAGLE], is disabled. Default is
true
.useSecureTransport
of type booleantrue
if socket uses SSL or TLS. Default is
false
.Use of secure transport needs more investigation
TCPServerOptions
States the options for the TCPServerSocket. An instance of this dictionary can optionally be used in the constructor of the TCPServerSocket object, where all fields are optional.
dictionary TCPServerOptions {
DOMString localAddress;
unsigned short localPort;
boolean addressReuse;
boolean useSecureTransport;
};
TCPServerOptions
MembersaddressReuse
of type booleantrue
allows the socket to be bound to a local
address/port pair that already is in use. Default is
true
.localAddress
of type DOMStringlocalPort
of type unsigned shortuseSecureTransport
of type booleantrue
if socket uses SSL or TLS. Default is
false
.Use of secure transport needs more investigation
enum SocketReadyState {
"opening",
"open",
"closing",
"closed",
"halfclosed"
};
Enumeration description | |
---|---|
opening | The socket is in opening state, i.e. availability of local address/port is being checked, network status is being checked, etc. For TCP a connection with a remote peer has not yet been established. |
open | The socket is ready to use to send and received data. For TCP a connection with a remote peer has been established. |
closing | Only used for TCP sockets. The TCP connection is going through the closing handshake, or the close() method has been invoked. |
closed | The socket is closed and can not be use to send and received data. For TCP the connection has been closed or could not be opened. |
halfclosed | Only used for TCP sockets. The TCP connection has been "halfclosed" by the application, which means that it is not possible to send data but it is still possible to receive. |
Many thanks to Domenic Denicola, Marcos Caceres, Jonas Sicking, Ke-Fong Lin and Alexandre Morgaut for reviewing the specification and providing very valuable feedback. Also thanks to Sony colleagues Anders Edenbrandt, Anders Isberg and Björn Isaksson for sharing their experience on socket APIs and providing support.