Вам нужно разделить ваши задачи. Одним из них является запуск gui, а другим - запуск сервера.
Сделайте одну задачу сервером.
public void runServer() throws Exception{
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
InetSocketAddress hostAddress = new InetSocketAddress("localhost", 0);
serverChannel.bind(hostAddress);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyCount = selector.select();
if (readyCount == 0) {
continue;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// get client socket channel
SocketChannel client = server.accept();
// Non Blocking I/O
client.configureBlocking(false);
// record it for read/write operations (Here we have used it for read)
client.register(selector, SelectionKey.OP_READ);
continue;
}
}
}
}
}
Затем сделайте другую задачу gui.
public void startGui(){
JPanel panel = new JPanel(new FlowLayout());
JButton start = new JButton("Start");
add(panel);
panel.add(start);
setTitle("Server");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
Теперь ваш основной метод может быть уменьшен до.
public static void main(String[] args) throws Exception{
Server server = new Server();
EventQueue.invokeAndWait( server::startGui );
server.runServer();
}
Таким образом, gui запускается на EDT, и сервер l oop, который никогда не завершается, занимает основной поток. Еще одно небольшое изменение. Не расширяйте JFrame, просто создайте JFrame в методе start Gui. Таким образом вся gui работа выполняется на EDT.
Не то чтобы я также удалил вашу обработку исключений и просто заставил методы вызывать исключение. Таким образом, вы увидите StackTrace.
В связи с вашим новым вопросом, почему gui зависает. Это потому что ваша блокировка на EDT. Ваш start()
метод никогда не завершается. Самый грубый способ исправить это:
public void actionPerformed(ActionEvent e) {
if(e.getSource()==start){
new Thread( ()->start();).start();
}
}
Что это будет делать, это запустить новый поток для запуска вашего сервера. Обратите внимание на наиболее очевидную проблему: если вы нажмете кнопку «Пуск» более одного раза, она запустит несколько потоков!