Привет, ребята, я работаю над серверной программой, предназначенной для масштабирования и обслуживания потенциально тысяч клиентов. Дело в том, что я чувствую, что Apache MINA слишком тяжелый, поэтому я решил не использовать его и вместо этого написал своего собственного слушателя. Я никогда не выполнял операции асинхронного сокета в Java (C# сделал это намного проще, но я действительно предпочел написать этот проект на Java, так как я больше знаком с ним во всем, кроме чтения сокетов), поэтому, пытаясь понять, как использовать поток пула правильно для меня. Я использовал документацию Apache MINA, чтобы понять, как все должно быть сделано. У меня было два вопроса:Помощь, необходимая для асинхронного Java NIO с использованием Executors.newFixedThreadPool
- Правильно ли используется пул потоков? Размер потока по умолчанию Apache MINA - это число ядер процессора + 1, но должен ли я использовать пул потоков 3 потоков для моего Core 2 Duo, чтобы принимать тысячи клиентов?
- Я знаю, что перераспределение буфера дважды за каждое сообщение, полученное от клиента (каждое сообщение представляет собой два пакета, один заголовок - постоянный 4 байта и пакет контента, длина которого указана в заголовке). Есть ли простой способ использовать буфер фиксированного размера, который проверяет переполнение буфера, так что поведение остается тем же, но буфер не нужно постоянно перераспределять?
Вот как я начинаю слушателя:
ClientListener cl = new ClientListener(1234);
cl.init();
new Thread(cl).start();
Вот соответствующий код ClientListener:
private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1;
private ServerSocket socket;
private ExecutorService threadPool;
private int port;
public ClientListener(int port) {
this.port = port;
threadPool = Executors.newFixedThreadPool(THREADS);
}
public void init() {
try {
socket = new ServerSocket(port);
} catch (IOException ex) {
}
}
public void run() {
while (true) {
try {
ClientSession s = new ClientSession(socket.accept());
threadPool.execute(s);
} catch (IOException ex) {
}
}
}
ClientSession соответствующий код:
private Socket socket;
private byte[] buffer;
private boolean isHeader;
public ClientSession(Socket socket) {
this.socket = socket;
this.buffer = new byte[4];
this.isHeader = true;
}
public void run() {
InputStream in;
try {
in = socket.getInputStream();
out = socket.getOutputStream();
} catch (IOException ex) {
return;
}
while (!socket.isClosed()) {
try {
int read = in.read(buffer);
if (read == -1)
break;
receive(read);
} catch (IOException ex) {
break;
}
}
}
private void receive(int readBytes) {
if (isHeader) {
if (readBytes >= 4) {
buffer = new byte[getPacketLength(buffer)];
isHeader = false;
} else {
System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet.");
}
} else {
if (readBytes >= buffer.length) {
processMessage(new LittleEndianByteArrayReader(decryptData(buffer)), this);
buffer = new byte[4];
isHeader = true;
} else {
System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet (needed " + buffer.length + ", received " + readBytes + ").");
}
}
}
Вы не нужно знать код для getPacketLength, processMessage, decrypt Data и класс LittleEndianByteArrayReader, но я уверен, что цели этих методов/классов очевидны.
что вы торчит, что вы просто глотаете исключения. По крайней мере, зарегистрируйте их. – dogbane
Это всего лишь фрагменты кода. В моем фактическом коде я записываю их с помощью java.util.Logger с подробными сообщениями. –
Вы вообще не используете NIO? Для этого вам понадобится Селектор. –