Copyright © 2025 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license 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 https://www.w3.org/TR/.
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 document was published by the System Applications Working Group as an Editor's Draft.
Comments regarding this document are welcome. Please send them to public-sysapps@w3.org (archives).
Publication as an Editor's 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 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 1 March 2019 W3C Process Document.
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 in this document is to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
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 term webapp refers to a Web application, i.e. an application implemented using Web technologies, and executing within the context of a Web user agent, e.g. a Web browser or other Web runtime environment.
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 is a security and privacy sensitive API and a webapp must have permission to use the API. The manner in which permission is given or not varies depending on the type of web runtime environment in which this API is implemented and could be based on:
The UDPPermission, TCPPermission and TCPServerPermission
interfaces provides a method hasPermission
that retrieves
the permission state for the requesting webapp and a method
requestPermission
that requests permission for the webapp
to use the socket interface. If a webapp calls the contructor of a
socket interface for which it has not permission to access the
user agent MUST immediately throw DOMException
"SecurityError"
.
The idea behind the UDPPermission, TCPPermission and
TCPServerPermission interfaces is to isolate the permission
system from the socket interfaces specifications. The manner in which
permission to use this API differs depending on the type of web runtime
it is implemented in. For example, a web runtime for secure installed
web applications may be able to open up this API so that no explicit
user content is needed, while an implementation in a web browser may
use a combination of web security mechanisms, such as secure transport
(https:), content security policies (CSP) and a signed manifest,
and user consent to open up the API.
The Permissions API,
which currently is an unofficial draft, is an API that allows a web
application to be aware of the status of a given permission, to know
whether it is granted, denied or if the user will be asked whether the
permission should be granted or not. If this API gets consensus and
becomes a W3C standard, and also is extended to support permission
requests, it may be possible to replace the hasPermission
and requestPermission
methods in this specification with
a reference to the Permission API.
W3C has activities on security for web applications, see
Web Application Security Working Group
and on trust and permissions, see
Workshop on trust and permissions for Web applications 3–4 September
2014, Paris, France and
Trust & Permissions Community Group.
The CSP directive connect-src
is used to restrict the allowed connection targets for XHR, Web Sockets
and Server-Sent Events. It should be considered if connect-src
should be extended to support allowed remote peers for raw TCP and UDP
sockets as well. However, currently the allowed connection targets for connect-src
are defined as a Source List
and this assumes URI schemes. So, schemes for UDP and TCP, i.e. udp:
and tcp:, might have to be defined. See address + port vs uri.
This interface exposes methods related to the permission to access the UDPSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.
This method MUST run the following steps asynchronously:
udpPermissionPromise
,
return it and run the remaining steps asynchronously.udpPermissionOptions
argument.udpPermissionPromise
with no arguments and abort the remaining steps.udpPermissionPromise
with TCPUDPPermissionState providing the permission
state. This method MUST run the following steps asynchronously:
udpRequestPermissionPromise
,
return it and run the remaining steps asynchronously.tcpRequestPermissionPromise
with DOMException "SecurityError"
and
abort the remaining steps.tcpRequestPermissionPromise
with DOMException "SecurityError"
and
abort the remaining steps.udpRequestPermissionPromise
and abort the remaining
steps.udpRequestPermissionPromise
and abort the remaining steps.udpRequestPermissionPromise
with DOMException "SecurityError"
. This interface exposes methods related to the permission to access the TCPSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.
This method MUST run the following steps asynchronously:
tcpPermissionPromise
,
return it and run the remaining steps asynchronously.tcpPermissionPromise
with no arguments and abort the remaining steps.tcpPermissionPromise
with TCPUDPPermissionState providing the permission
state. This method MUST run the following steps asynchronously:
tcpRequestPermissionPromise
,
return it and run the remaining steps asynchronously.tcpRequestPermissionPromise
with DOMException "SecurityError"
and
abort the remaining steps.tcpRequestPermissionPromise
and abort the remaining
steps.tcpRequestPermissionPromise
and abort the remaining steps.tcpRequestPermissionPromise
with DOMException "SecurityError"
. This interface exposes methods related to the permission to access the TCPServerSocket interface. Permission could be given based on user consent, based on trust for the webapp, e.g. related to the origin of it and verified through web security mechanisms such as secure transport and signatures, based on previously granted or denied permission explicitly for this webapp or a combination of these mechanisms.
This method MUST run the following steps asynchronously:
tcpServerPermissionPromise
,
return it and run the remaining steps asynchronously.tcpServerPermissionOptions
argument.tcpServerPermissionPromise
with no arguments and abort the remaining steps.tcpServerPermissionPromise
with TCPUDPPermissionState providing the permission
state. This method MUST run the following steps asynchronously:
tcpServerRequestPermissionPromise
,
return it and run the remaining steps asynchronously.tcpServerRequestPermissionPromise
with DOMException "SecurityError"
and
abort the remaining steps.tcpServerRequestPermissionPromise
and abort the
remaining steps.tcpServerRequestPermissionPromise
and abort the remaining steps.tcpServerRequestPermissionPromise
with DOMException "SecurityError"
. 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 = ''; // Request permission to send multicast messages to the address and // port reserved for SSDP navigator.udpPermission.requestPermission({remoteAddress:"239.255.255.250", remotePort:1900}).then( () => { // Permission was granted // 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.ready.then(receiveMSearchResponses); } // 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); ); }, e => console.error("Sending SSDP multicast messages was denied due to error: ", e); );
options
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
.options
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. 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
.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
.openedPromise
that was created in the
UDPSocket
constructor.
close()
) or
through an error situation, e.g. network contact lost.
Returns the closedPromise
that was created
in the UDPSocket
constructor.
Closes the UDP socket. Returns the closedPromise
that
was created in the UDPSocket
constructor.
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).
Leaves a multicast group membership identified by the given address.
When the UDPSocket constructor is invoked, the user agent MUST run the following steps:
mySocket
").
options
argument then throw DOMException "SecurityError"
and
abort the remaining steps.
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. 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. A webapp should use .ready 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.
remoteAddress
and/or remotePort
member(s) are present but
the webapp does not have permission to send UDP
packets to this address and port then throw DOMException
SecurityError
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 webapp should use .ready
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 webapp.
The close
method when invoked MUST run the
following steps:
closedPromise
.
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. // // Request permission to connect to server at address 127.0.0.1 on port // 6789 navigator.tcpPermission.requestPermission({remoteAddress:"127.0.0.1", remotePort:6789}).then( () => { // Permission was granted // 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.ready.then( () => { // Data in buffer, read it console.log("Data received from server:" + mySocket.readable.read()); // Close the TCP connection mySocket.close(); } ); }, 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 webapp // 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); ); }, e => console.error("Connection to 127.0.0.1 on port 6789 was denied due to error: ", e); );
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
. options
argument in the constructor. If not set the
user agent binds the socket to an ephemeral local port decided by
the system. 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
.true
if the Nagle algorithm for send coalescing,
[NAGLE], is disabled. Can be set by the
options
argument in the constructor. Default is
true
.openedPromise
that was created
in the TCPSocket
constructor.
close()
) or through an error situation.
Returns the closedPromise
that was created
in the TCPSocket
constructor.
Closes the TCP socket. Returns the closedPromise
that
was created in the TCPSocket
constructor.
Half closes the TCP socket.
When the TCPSocket constructor is invoked, the user agent MUST run the following steps:
mySocket
").
remoteAddress
/remotePort
as stated by the input arguments, then throw DOMException
"SecurityError"
and abort the remaining steps.
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. A webapp should use .ready 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 webapp should use .ready
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.
mySocket
")
to the webapp.
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()
.
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. // // Request permission to listen on port 6789 navigator.tcpServerPermission.requestPermission({"localPort":6789}).then( () => { // Permission was granted // 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.ready.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 (); } ); } // 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 webapp // 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); ); }, e => console.error("TCP Server Socket on local port 6789 was denied due to error: ", e); );
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
.
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
.
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
.openedPromise
that was created in the
TCPServerSocket
constructor.
close()
) or through
an error situation. Returns the closedPromise
that
was created in the TCPSocket
constructor.
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.
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.
When the TCPServerSocket constructor is invoked, the user agent MUST run the following steps:
myServerSocket
").
options
argument then throw DOMException "SecurityError"
and
abort the remaining steps.
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.
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:
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"
.
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.
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.
remoteAddress
if this member is present. Else the
UDPSocket is unbound to a local interface. true
allows the socket to be bound to a local address/port pair that
already is in use. Default is true
.true
means that sent
multicast data is looped back to the sender.
Default is false
.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.
remoteAddress
. true
allows the socket to be bound to a local
address/port pair that already is in use. Default is true
.
true
if the Nagle algorithm for send coalescing,
[NAGLE], is disabled. Default is
true
.true
if socket uses SSL or TLS. Default is
false
.Use of secure transport needs more investigation
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.
true
allows the socket to be bound to a local
address/port pair that already is in use. Default is
true
.true
if socket uses SSL or TLS. Default is
false
.Use of secure transport needs more investigation
States the options for the webapp to get status of permission
for creating a UDPSocket object or to request permission to
create a UDPSocket object. An instance of this dictionary can
optionally be used as argument to the UDPPermission hasPermission
and requestPermission
methods. All fields are optional.
States the options for the webapp to get status of permission
for creating a TCPSocket object or to request permission to
create a TCPSocket object. An instance of this dictionary can
optionally be used as argument to the TCPPermission hasPermission
and requestPermission
methods. All fields are optional.
States the options for the webapp to get status of permission
for creating a TCPServerSocket object or to request permission to
create a TCPServerSocket object. An instance of this dictionary can
optionally be used as argument to the TCPServerPermission
hasPermission
and requestPermission
methods.
All fields are optional.
requestPermission
.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.