com.github.luohaha.worker.Accepter Maven / Gradle / Ivy
package com.github.luohaha.worker;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.github.luohaha.param.ServerParam;
public class Accepter extends Worker implements Runnable {
private ServerSocketChannel channel;
private Selector selector;
private ServerParam param;
private List workers = new ArrayList<>();
private int workerIndex = 0;
public Accepter(ServerParam param) {
this.selector = openSelector("[Accepter] open selector");
this.channel = openServerSocketChannelNonBlocking("[Accepter] open server socket channel");
this.param = param;
bindAddress(this.channel, this.param);
}
/**
* add worker thread
*
* @param worker
* worker
*/
public void addIoWorker(IoWorker worker) {
workers.add(worker);
}
public void accept() {
registerChannel();
// select
while (true) {
try {
this.selector.select();
Set keys = this.selector.selectedKeys();
Iterator iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
handle(key);
iterator.remove();
}
} catch (IOException e) {
this.logger.warning("[Accepter] select : " + e.toString());
this.selector = openSelector("[Accepter] select : ");
registerChannel();
}
}
}
private void handle(SelectionKey key) {
if (key.isAcceptable()) {
/*
* accept
*/
ServerSocketChannel server = (ServerSocketChannel) key.channel();
try {
SocketChannel channel = server.accept();
this.logger.info("[Accept] accept : " + channel.getRemoteAddress().toString());
IoWorker worker = workers.get(workerIndex);
worker.dispatch(new JobBean(channel, this.param));
workerIndex = (workerIndex + 1) % workers.size();
} catch (IOException e) {
// accepter error
this.logger.warning("[Accept] accept : " + e.toString());
if (param.getOnAcceptError() != null) {
param.getOnAcceptError().onAcceptError(e);
}
registerChannel();
}
}
}
@Override
public void run() {
accept();
}
/**
* bind address
*
* @param serverSocketChannel
* serverSocketChannel
* @param serverParam
* serverParam
*/
private void bindAddress(ServerSocketChannel serverSocketChannel, ServerParam serverParam) {
do {
try {
serverSocketChannel.socket().bind(new InetSocketAddress(serverParam.getHost(), serverParam.getPort()),
serverParam.getBacklog());
break;
} catch (IOException e) {
this.logger.warning("[Accepter] bind address : " + e.toString());
}
} while (true);
}
/**
* register
*/
private void registerChannel() {
// register
do {
try {
this.channel.register(this.selector, SelectionKey.OP_ACCEPT);
break;
} catch (ClosedChannelException e) {
this.logger.warning("[Accepter] register : " + e.toString());
this.channel = openServerSocketChannelNonBlocking("[Accepter] open server socket channel ");
bindAddress(this.channel, this.param);
}
} while (true);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy