public interface TcpConnection
This interface is a higher abstraction over TcpChannel
.
See TcpChannel2Connection
for converting a TcpChannel to TcpConnection.
This interface may also represent an SSL connection, see subtype SslConnection
.
This connection maintains a queue of ByteBuffers to be written.
Append a ByteBuffer to the queue by queueWrite(ByteBuffer)
.
Queued data are not automatically written, you have to call write()
.
After write(), if getWriteQueueSize()
does not reach 0,
the connection is temporarily un-writable, and you may call awaitWritable()
before write() again.
Sentinel values TCP_FIN
and SslConnection.SSL_CLOSE_NOTIFY
can also be queued,
each counted as 1 byte in the queue size.
This class is generally not thread-safe. For example, if two threads call read() concurrently,
the behavior is undefined, and probably disastrous.
Usually, you'll use the connection executor
for all connection-related tasks, and they will be executed in serialized order.
Modifier and Type | Field and Description |
---|---|
static ByteBuffer |
STALL
Sentinel value for read(), meaning nothing is available for read at the moment.
|
static ByteBuffer |
TCP_FIN
Sentinel value for read() and queueWrite(), representing TCP FIN.
|
Abstract Methods | |
---|---|
long |
getId()
Get the ID of this connection.
|
String |
getPeerHost()
Get the host name of the peer; or null if unknown.
|
InetAddress |
getPeerIp()
Get the IP address of the peer.
|
int |
getPeerPort()
Get the TCP port of the peer.
|
ByteBuffer |
read()
Read data from the peer.
|
void |
unread(ByteBuffer bb)
Unread data.
|
Async<Void> |
awaitReadable(boolean accepting)
Wait till this connection becomes readable.
|
long |
queueWrite(ByteBuffer bb)
Append the ByteBuffer to the write queue.
|
long |
getWriteQueueSize()
Get the total remaining bytes of the write queue ByteBuffers.
|
long |
write()
Write bytes from the head of the write queue.
|
Async<Void> |
awaitWritable()
Wait till this connection becomes writable.
|
Async<Void> |
close(Duration drainTimeout)
Close this connection.
|
Executor |
getExecutor()
Get an executor associated with this connection.
|
static final ByteBuffer STALL
static final ByteBuffer TCP_FIN
long getId()
The ID is for diagnosis only. It is unique within each server/client.
String getPeerHost()
If the host name is unknown, this method does not lookup the host name from the peer IP.
InetAddress getPeerIp()
int getPeerPort()
ByteBuffer read() throws Exception
This method returns sentinel values or some real data.
STALL
- nothing is available for read at the moment.
You may awaitReadable(boolean)
before read again.
TCP_FIN
or SslConnection.SSL_CLOSE_NOTIFY
- TCP FIN or SSL close-notify record is received.
After that, read() should not be called again.
The caller of read() must check for the sentinel values first (using ==).
Exception
void unread(ByteBuffer bb) throws IllegalStateException
Next read() will see the ByteBuffer bb.
Only one unread is supported at a time. Two consecutive unread() calls is illegal.
IllegalStateException
Async<Void> awaitReadable(boolean accepting)
This method is typically called after a previous read() returns STALL.
There can be only one pending awaitReadable action at any time.
Spurious wakeup is possible - this action may succeed yet the next read() sees STALL again.
See TcpChannel.awaitReadable(boolean)
for more details.
long queueWrite(ByteBuffer bb)
The ByteBuffer is now owned by this connection. If it's from a shared/cached source,
pass a duplicate
to this method.
The ByteBuffer can be very small, e.g. "\r\n", or very large, e.g. a cached huge buffer.
Sentinel values TCP_FIN
and SslConnection.SSL_CLOSE_NOTIFY
can also be queued,
each counted as 1 byte in the queue size. If this connection is not SSL,
queueWrite(SSL_CLOSE_NOTIFY)
is a no-op.
Any app data must be queued before SSL_CLOSE_NOTIFY, which must be queued before TCP_FIN.
long getWriteQueueSize()
long write() throws Exception
When this method returns, either write queue is cleared, or send buffer is full.
If getWriteQueueSize()
does not decrease to 0 after write(),
this connection is temporarily un-writable (because send-buffer is full).
You may awaitWritable()
then try write() again.
Exception
Async<Void> awaitWritable()
This method is typically called after a previous write() didn't clear the write queue. This action will wait for more rooms in the send buffer.
There can be only one pending awaitWritable action at any time.
This action succeeds when this connection become writable (next write() should be able to write more bytes), or fails due to cancellation, channel being closed, server shutdown etc.
Spurious wakeup is possible - this action may succeed yet the next write() returns 0 (no byte is written).
Async<Void> close(Duration drainTimeout)
Data in the write queue are abandoned. The TCP connection will be closed.
If `drainTimeout` is non-null and positive, we will attempt to drain the inbound TCP bytes (till FIN is received) before we actually close the TCP connection. This is to avoid the infamous TCP RST problem - if the connection is closed without draining the inbound, the peer may not received the data we have sent.
The draining step is unnecessary if the app protocol is properly designed, which knows that there's no inbound data at the time of close.
The draining step can also be skipped if FIN was seen in a previous read(), or app wants to kill the connection immediately.
Executor getExecutor()
The executor can be used to execute non-blocking tasks related to this connection. Tasks will be executed sequentially in the order they are submitted.