public abstract class AbstractSocketChannelConnection extends Object
Abstract base class for handling a connection based on a
SocketChannel
.
This class implements the low-level details of dealing with a non-blocking
socket-channel. Classes inherting from this class can simply write to a
ByteSink
and read from a ByteSource
. This class takes care of
registering the right operations with the channel's Selector
and
managing internal buffers.
This class is not safe for use by multiple threads. All of its methods
(except for the destroy()
method) may only be called from the
communication controller's thread. This can easily be achieved by
implementing all logic in the event methods (on...
).
This class is highly configurable. The size of an individual
ByteBuffer
, the number of unused byte buffers that are kept on a free
list, and the maximum number of bytes that are read contiguously can be
configured at construction time.
Constructor and Description |
---|
AbstractSocketChannelConnection(SocketChannel channel,
CommunicationController communicationController,
ErrorHandler errorHandler,
int bufferSize,
int maximumNumberOfFreeBuffers,
long maximumNumberOfContiguousBytesRead)
Creates a connection based on a socket channel.
|
Modifier and Type | Method and Description |
---|---|
protected void |
destroy()
Destroys this connection.
|
protected ByteSource |
getReceiveSource()
Returns the byte source that contains the data received by this
connection.
|
protected long |
getSendQueueSizeInBytes()
Returns the number of bytes that have been written to the byte sink but
have not been sent yet.
|
protected ByteSink |
getSendSink()
Returns the byte sink that can be used to send data over this connection.
|
protected boolean |
isDestroyed()
Tells whether this connection has been destroyed.
|
protected void |
onConnect()
Called when the socket channel is connected.
|
protected void |
onDestroy()
Called when this connection has been destroyed.
|
protected long |
onReceive()
Called when data is received.
|
protected void |
onReceiveFinished(boolean moreDataAvailable)
Called when a data receive operation is finished.
|
protected void |
onSend()
Called whenever data has been sent.
|
protected void |
tryReceive()
Tries to read data from the channel.
|
protected void |
trySend()
Tries to write data to the channel.
|
public AbstractSocketChannelConnection(SocketChannel channel, CommunicationController communicationController, ErrorHandler errorHandler, int bufferSize, int maximumNumberOfFreeBuffers, long maximumNumberOfContiguousBytesRead)
channel
has to be configured for non-blocking operation and must be connected or
a connection must be pending.channel
- socket channel that represents the connection (never
null
).communicationController
- communication controller used by this connection (never
null
).errorHandler
- error handler that is used to log unexpected I/O errors (never
null
). Only errors that are typically not caused
by an interrupted connection are considered unexpected.bufferSize
- size of each byte buffer that is allocated by this class. Must
be greater than zero and should (but does not have to be) a
power of two. Larger buffers typically improve the performance
but can have a large memory footprint if they are not filled
completely. However, this class avoids partially filled
buffers by reusing them whenever possible. Therefore, the
impact on memory usage should be negligible.maximumNumberOfFreeBuffers
- maximum number of unused buffers to keep on the free list.
Must be greater than or equal to zero. This class uses direct
buffers which typically incur significant allocation cost.
Therefore, allowing for a larger number of unused buffers to
be kept can improve the performance but might increase the
memory footprint.maximumNumberOfContiguousBytesRead
- maximum number of bytes that are read in a single operation.
If zero or negative, the number is not limited. This parameter
can be used to avoid staying in the receive loop forever when
data arrives faster than it can be processed. When a limit is
set and the receive loop detects that the last read operation
hit or surpassed this limit, it will quit the loop, thus
returning control back to the communication controller. This
way, the communication controller is able to process other
pending actions, including, but not limited to, send
operations for this object.IllegalArgumentException
- if one of the parameters passed to this method is invalid.
Invalid parameters are a channel
that is not
configured for non-blocking operation or that is not
connected and no pending connection attempt, a
bufferSize
less than one, and a
maximumNumberOfFreeBuffers
less than zero.protected void tryReceive()
Tries to read data from the channel. This method reads, until there is no
more data available (the read returns no data), there is an
IOException
, or the maximum number of contiguous bytes to be
received is reached. When data is received. the onReceive()
method is called. Before returning, the
onReceiveFinished(boolean)
is called.
This method catches all IOException
s. If such an exception is
caught, the connection is destroyed by calling destroy()
. If the
connection is pending (a connect operation has been started but has not
finished yet), this method does not try to read but returns immediately.
onReceiveFinished(boolean)
is not called.
Typically, this method does not have to be called explicitly. It will automatically be triggered, when data becomes available for reading. However, derived classes can call it explicitly if they want to run this method when it would normally not be run (e.g. when no data is available or when other operations like sending data would usually be run first).
This method may only be called from the communication controller's thread.
protected void trySend()
Tries to write data to the channel. This method writes, until there is no
more data available (the send sink is empty), there is an
IOException
, or the channel does not accept more data. Before
returning, the onSend()
method is called if any data has been
written.
This method catches all IOException
s. If such an exception is
caught, the connection is destroyed by calling destroy()
. If the
connection is pending (a connect operation has been started but has not
finished yet), this method does not try to write but returns immediately.
Typically, this method does not have to be called explicitly. It will automatically be triggered, when there is data in the send sink and the channel is ready for writing. However, derived classes can call it explicitly if they want to run this method when it would normally not be run (e.g. or when other operations like receiving data would usually be run first).
This method may only be called from the communication controller's thread.
protected boolean isDestroyed()
destroy()
method is called. The destroy
method is called when an I/O exception occurs, but it might also be
called explicitly by derived classes.true
if this connection has been destroyed,
false
if it has not been destroyed yet.protected ByteSource getReceiveSource()
remaining()
method accurately. This means
that reading more bytes than indicated by this method will always result
in a BufferUnderflowException
. If the method indicates that there
are Integer.MAX_VALUE
bytes remaining, the actual number of bytes
remaining might be larger.null
).protected ByteSink getSendSink()
null
).protected long getSendQueueSizeInBytes()
Long.MAX_VALUE
, this value is returned. The number returned can
be used to determine whether more data should be added to the queue or
whether this should be postponed until some of the data in the queue has
been sent. This method may only be called from the communication
controller's thread.protected void onConnect()
protected void onDestroy()
destroy()
method is called explicitly. This
method will never be called more than once. This method is called in the
thread which calls the destroy()
method.protected long onReceive()
getReceiveSource()
. If this method returns a number greater than
zero, it will only be called again when at least this number of bytes
have been received (in addition to the bytes that already have been
received and are available from the byte source). This method is
guaranteed to be called in the communication controller's thread.protected void onReceiveFinished(boolean moreDataAvailable)
moreDataAvailable
- true
if more data is available from the channel
but the read operation has been interrupted because the limit
for the maximum number of contiguous bytes read has been
reached. false
if currently there is no more data
available from the channel.protected void onSend()
getSendQueueSizeInBytes()
. This method is
guaranteed to be called in the communication controller's thread.protected void destroy()
onDestroy()
method. This
method may be called from any thread. If the connection has already been
destroyed, calling this method has no effect. The onDestroy
method is called before this method returns.Copyright © 2014–2017 aquenos GmbH. All rights reserved.