Мой однопоточный сервер должен загружать архив подключившемся клиентам. Пока я могу передавать файл всего одному клиенту за раз, что меня не устраивает. Я ищу простой способ убрать блокировку или ещё как-то решить проблему (желательно без костылей).
P. S. сервер работает в отдельном потоке
class TCPServer implements Runnable {
private InetSocketAddress address;
private ServerSocketChannel serverSocketChannel;
private Selector selector;
private static FileChannel channel;
TCPServer(String hostname, int port) throws IOException {
address = new InetSocketAddress(hostname, port);
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(address);
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
int select = 0;
select = selector.select();
if (select == 0)
continue;
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid())
continue;
if (key.isAcceptable())
accept(key);
if (key.isWritable())
write(key);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
closeConnections();
}
private void accept(SelectionKey key) throws IOException {
var serverSocketChannel = (ServerSocketChannel) key.channel();
var socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_WRITE);
}
private void write(SelectionKey key) throws IOException {
channel = FileChannel.open(Paths.get("/home/martin/file.zip"));
var socketChannel = (SocketChannel) key.channel();
var buffer = ByteBuffer.allocate(1024 * 4);
while (channel.read(buffer) != -1) {
buffer.flip();
socketChannel.write(buffer);
buffer.compact();
} key.channel().close();
}
private void closeConnections() {
try {
selector.close();
serverSocketChannel.socket().close();
serverSocketChannel.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}