A stream backed by a TCP socket.
While the socket stream supports both synchronous and asynchronous API, the latter is strongly recommended. In fact, the synchronous API is merely a wrapper on top of the asynchronous one.
After obtaining a socket, call Socket.getReadStream() or Socket.getWriteStream() to get a stream for either input or output. To read data off of the input stream, call readAsync() against a user-provided buffer. This method returns a Promise immediately, which will be settled at the earliest timing whenever some data of arbitrary size arrives. The caller may chain this promise to another one in which he usually calls some async API again: string s = "";
byte[] buffer = new byte[128];
Promise prom = stream.readAsync(buffer, 0)
.then((count, handle) => {
s += String.fromBytes(buffer, "ascii", 0, count);
return stream.readAsync(buffer, 0); // read some more
});
// The promise will settle only after both readAsync calls are finished in the scripted order.
However, since the size of data read from readAsync() is arbitrary, it would be difficult to write any application simply by recalling this method. Putting the call in a for
loop can work, but that would effectively serialize the dataflow and thus totally defeat the very purpose of using async API. The perfect solution to this dilemma it to call readToEndAsync() instead. This API allows user to call with a callback, which will be invoked upon arrival of each chunk of data. The method returns a promise that will be settled only after the connection is torn down: AsyncStream rs = sock.getReadStream();
AsyncStream ws = sock.getWriteStream();
byte[] rbuf = new byte[128], wbuf = new byte[128];
Promise prom = rs.readToEndAsync(rbuf, (count, handle) => {
if (count > 0) {
... // do something with contents in buffer
if (...) {
// write some data back
ws.writeAsync(wbuf, 0, wbuf.length);
} else if (...) {
// tear down connection at application level
handle.resolve(total);
}
}
});
The synchronous API is built on top of asynchronous calls. While they may appear to be more straightforward to use, they are in general not recommended for several reasons. In particular, do not mix sync and async calls together. The most dangerous case arises when you call some sync method in an async call back: // HIGH POSSIBILITY OF DEADLOCKING
AsyncStream rs = sock.getReadStream();
Promise prom = rs.readToEndAsync(rbuf, (count, handle) => { // async call
if (count > 0) {
rs.read(rbuf, offset, length); // sync call
}
});
The callback for async API is invoked on a special thread which is dedicated to post-IO operations. There are only a few such threads managed by the script engine. Since sync API is essentially also calling the async version, it's likely the operation is queued on the very same thread where the current callback is running.
Parent Class
Parent Interfaces
Type | Name | Signature |
---|---|---|
method | canRead | public bool canRead() |
method | canReadAsync | public bool canReadAsync() |
method | canWrite | public bool canWrite() |
method | canWriteAsync | public bool canWriteAsync() |
method | readAsync | public Promise readAsync(byte[], int) |
method | readToEndAsync | public Promise readToEndAsync(byte[], Function) |
method | writeAsync | public Promise writeAsync(byte[], int, int) |
public bool canRead()
Returns
public bool canReadAsync()
(INHERITED DOC)
Whether this stream supports asynchronous reading. This method governs readAsync, readAllAsync.
Returns
public bool canWrite()
Returns
public bool canWriteAsync()
(INHERITED DOC)
Whether this stream supports asynchronous writing. This method governs writeAsync.
Returns
public Promise readAsync(byte[] buffer, int offset)
(INHERITED DOC)
Read asynchronously from the stream to the buffer, and invokes callback upon completion.
This method tries to read as many bytes as possible from the stream into the given buffer, starting from the offset and not exceeding the buffer's capacity. This will move forward the stream pointer by the number of bytes actually read. If the stream hits the end, or the buffer runs short of room before reading the specified count, only those bytes will be read, making the returned value less than the count argument.
Upon successful completion, the callback function will be invoked. The callback function has signature Function(int, PromiseHandle)
, with first parameter indicating the number of bytes successfully read. If the reading failed, this callback won't be called, and the users must process that with a continuation on the promise itself.
This method moves forward the stream pointer by the count equal to returned value. If canRead() returns false, this method will throw IOException.
Required Policies
System.Socket/read
Parameters
Returns
public Promise readToEndAsync(byte[] buffer, Function callback)
(INHERITED DOC)
Read asynchronously from the stream to the buffer until the end of stream is hit, and invoke callback evertime a chunk of data is read, which usually fills the buffer, except for the last time.
This method tries to read as many bytes as possible from the stream into the given buffer. Everytime it reads a chunk of data, it will invoke the callback function, which has signature Function(int, PromiseHandle)
, with first parameter indicating the number of bytes successfully read. If the reading failed, this callback won't be called, and the users must process that with a continuation on the promise itself.
This method moves forward the stream pointer to the end of stream. If canRead() return false, this method will throw IOException.
Required Policies
System.Socket/read
Parameters
Function(int, PromiseHandle)
, first parameter indicating the number of bytes successfully read. -1 if reaching the end, while buffer will contain no valid bytes. Throughout the promise's life cycle this callback will be invoked multiple times.Returns
public Promise writeAsync(byte[] buffer, int offset, int length)
(INHERITED DOC)
Write asynchronously from the buffer to the stream.
This method tries to write all the bytes from the given buffer to the stream, starting from the offset and not exceeding either length or the buffer's capacity. This will move forward the stream pointer by the number of bytes actually written.
This method moves forward the stream pointer by the count equal to value used to settle the promise. If canWriteAsync() return false, this method will throw IOException.
Required Policies
System.Socket/write
Parameters
Returns