Напиши исправленный код сервера так, чтобы он мог правильно обрабатывать несколько клиентов. Используй асинхронные операции
package serverUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;

public class ConnectionManager {
    private static final String ACK_MESSAGE_PREFIX = "<%s>Ack";
    static final int BUFFER_SIZE = 1024 * 1024;

    ServerSocketChannel serverSocketChannel;
    int port;

    public ConnectionManager(int port) {
        this.port = port;
    }

    public void initialize() throws IOException {
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        serverSocketChannel.configureBlocking(false);
        System.out.println("Server started on port " + port);
                System.out.println("============ * ============");
    }

    public void registerSelector(Selector selector) throws ClosedChannelException {
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }

    public void acceptConnection(SelectionKey key, Selector selector) throws IOException {
        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientSocketChannel = serverSocketChannel.accept();

        if (clientSocketChannel != null) {
            clientSocketChannel.configureBlocking(false);

            // Производим регистрацию канала на чтение
            int ops = SelectionKey.OP_READ;
            ConnectionContext context = new ConnectionContext();
            clientSocketChannel.register(selector, ops, context);

            System.out.println("Connected: " + clientSocketChannel.getRemoteAddress());
        }
    }


    public void handleRead(SelectionKey key) throws IOException {
        SocketChannel clientSocketChannel = (SocketChannel) key.channel();
        ConnectionContext connectionContext = (ConnectionContext) key.attachment();

        if (connectionContext == null) {
            connectionContext = new ConnectionContext();
            key.attach(connectionContext);
        }

        ByteBuffer buffer = connectionContext.buffer;
        int bytesRead = clientSocketChannel.read(buffer);

        if (bytesRead < 0) {
            System.out.println("Closed connection with " + clientSocketChannel.getRemoteAddress());
            clientSocketChannel.close();
            key.cancel();
            return;
        }

        buffer.flip();

        // handle file transmission
        if (connectionContext.fileStarted) {
            if (connectionContext.fileName != null && connectionContext.fileLength >= 0 &&
                    buffer.remaining() >= connectionContext.fileLength) {

                byte[] fileContent = new byte[connectionContext.fileLength];
                buffer.get(fileContent);

                saveFile(connectionContext.fileName, fileContent);
                sendAck(clientSocketChannel, connectionContext.fileName);

                // reset context for next file transfer
                connectionContext.fileStarted = false;
                connectionContext.fileCompleted = true;

                // handle any remaining data in buffer if present
                if (buffer.remaining() > 0) {
                    buffer.compact();
                    handleRead(key);
                    return;
                }
            } else {
                buffer.compact(); // Оставляем данные в буфере для следующей итерации чтения
            }
        } else {
            while (buffer.hasRemaining() && !connectionContext.fileStarted) {
                // read the name length
                if (connectionContext.fileName == null && buffer.remaining() >= Integer.BYTES) {
                    int nameLength = buffer.getInt();
                    byte[] nameBytes = new byte[nameLength];
                    buffer.get(nameBytes);
                    connectionContext.fileName = new String(nameBytes, StandardCharsets.UTF_8);
                }

                // read the file length
                if (connectionContext.fileLength < 0 && buffer.remaining() >= Long.BYTES) {
                    connectionContext.fileLength = (int) buffer.getLong();
                    if (connectionContext.fileLength < 0) {
                        throw new RuntimeException("Invalid file length");
                    }
                    connectionContext.fileStarted = true;

                    // check if we need more data to continue reading the file
                    if (buffer.remaining() < connectionContext.fileLength) {
                        buffer.compact();
                        return;
                    }
                }
            }

            buffer.compact(); // Оставляем данные в буфере для следующей итерации чтения
        }

        if (!connectionContext.fileStarted || connectionContext.fileCompleted) {
            handleRead(key);
        }
    }



    private void saveFile(String filename, byte[] fileContent) throws IOException {
        File file = new File("files\\" + filename);

        System.out.println("Saving file " + filename);

        try (FileOutputStream outputStream = new FileOutputStream(file, true)) {
            int offset = 0;
            while (offset < fileContent.length) {
                int bytesToWrite = Math.min(BUFFER_SIZE, fileContent.length - offset);
                outputStream.write(fileContent, offset, bytesToWrite);
                outputStream.flush();
                offset += bytesToWrite;
            }
        }
        System.out.println("File " + filename + " saved successfully");
    }

    private void sendAck(SocketChannel clientSocketChannel, String filename) throws IOException {
        String ackMessage = String.format(ACK_MESSAGE_PREFIX, filename);
        byte[] ackMessageBytes = ackMessage.getBytes();
        ByteBuffer buffer = ByteBuffer.allocate(ackMessageBytes.length + Integer.BYTES);
        buffer.putInt(ackMessageBytes.length);
        buffer.put(ackMessageBytes);
        buffer.flip();

        while (buffer.hasRemaining()) {
            clientSocketChannel.write(buffer);
        }

        System.out.println("Sent acknowledgement for " + filename);
        buffer.clear(); // Очищаем буфер перед чтением новых данных
    }
}

package serverUtils;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;

public class Console {

    public void start() throws IOException {
        ConnectionManager connectionManager = new ConnectionManager(6789);
        connectionManager.initialize();

        Selector selector = Selector.open();
        connectionManager.registerSelector(selector);

        while (true) {
            int readyChannelsCount = selector.select();
            if (readyChannelsCount == 0) {
                continue;
            }

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> selectionKeyIterator = selectedKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey key = selectionKeyIterator.next();
                selectionKeyIterator.remove();

                if (!key.isValid()) {
                    continue;
                }

                // Произведем проверку на то, что ключ готов для подключения
                if (key.isAcceptable()) {
                    connectionManager.acceptConnection(key, selector);
                }

                // Проверка на возможность чтения данных из канала
                if (key.isReadable()) {
                    connectionManager.handleRead(key);
                }
            }
        }
    }
}