TcpServerHandler.java
package space.sunqian.common.net.tcp;
import space.sunqian.annotations.Nonnull;
import space.sunqian.annotations.Nullable;
import space.sunqian.common.io.communicate.ChannelHandler;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
/**
* Handler for handling tcp server events for TCP network server, based on {@link ServerSocketChannel} and
* {@link SocketChannel}.
* <p>
* All callbacks triggered by events from the same underlying channel will use the same {@link TcpContext} instance,
* ensuring consistent access to channel-specific state and attachments throughout the channel's lifecycle.
*
* @author sunqian
*/
public interface TcpServerHandler extends ChannelHandler<TcpContext, SocketChannel> {
/**
* Returns an instance of {@link TcpServerHandler} that does nothing but discards received data.
*
* @return an instance of {@link TcpServerHandler} that does nothing but discards received data
*/
static @Nonnull TcpServerHandler nullHandler() {
return NullServerHandler.INST;
}
/**
* This method is invoked after a new channel is opened, and only once for each new channel.
*
* @param context the context for the new channel
* @throws Exception for any error
*/
@Override
void channelOpen(@Nonnull TcpContext context) throws Exception;
/**
* This method is invoked after a channel is closed, and only once for each channel.
*
* @param context the context for the closed channel
* @throws Exception for any error
*/
@Override
void channelClose(@Nonnull TcpContext context) throws Exception;
/**
* This method is invoked after the server receives data.
* <p>
* If the read method of the channel returns {@code -1}, it means the channel can no longer be read (usually because
* the peer sent a {@code FIN} and entered the half-closed state). In this case, the channel can be closed to
* complete the close operation. If it returns {@code 0}, it indicates that all available data from the current read
* event has been read, but the channel remains alive.
*
* @param context the context for the channel where the data is received
* @throws Exception for any error
*/
@Override
void channelRead(@Nonnull TcpContext context) throws Exception;
/**
* This method is invoked for all active clients in the event loop after each selector wake-up
* ({@link Selector#select(long)}). It can be used to uniformly handle some issues, such as connection heartbeats.
* <p>
* Note the default implementation does nothing.
*
* @param context the context for the active channel
* @throws Exception for any error
*/
default void channelLoop(@Nonnull TcpContext context) throws Exception {
}
/**
* This method is invoked after catching an unhandled exception, the exception may come from this handler or from
* the container running this handler.
* <p>
* The behavior is undefined if this method still throws an exception.
*
* @param context the context parameter of the method where this handler throws the exception, may be {@code null}
* if the exception is not thrown from this handler
* @param cause the unhandled exception
*/
@Override
void exceptionCaught(@Nullable TcpContext context, @Nonnull Throwable cause);
}