Java - про сокет: как сменить поток без перезагрузки сервера - PullRequest
0 голосов
/ 03 ноября 2011

Возникла проблема с сервером-клиентом:

Когда сервер работает, если я хочу внести некоторые изменения в ServerThread, например, строка «Добро пожаловать!» на «Привет!», это возможно выполнить без перезагрузки сервера? На данный момент, когда я меняю "Добро пожаловать!" к чему-то еще, это все еще распечатывает "Добро пожаловать!" клиенту. Я должен закрыть затмение и перезапустить сервер для работы этой новой строки. Есть ли способ решить эту проблему? Большое спасибо!

Сервер:

import java.net.*;
import java.io.*;

public class ATMServer {

    private static int connectionPort = 8989;
    public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = null;
    boolean listening = true; 
    try {
        serverSocket = new ServerSocket(connectionPort); 
    } catch (IOException e) {
        System.err.println("Could not listen on port: " + connectionPort);
        System.exit(1);
    }

    System.out.println("Bank started listening on port: " + connectionPort);
    while (listening)
        new ATMServerThread(serverSocket.accept()).start();
    serverSocket.close();
    }
}

ServerThread:

import java.io.*;
import java.net.*;

public class ATMServerThread extends Thread {
    private Socket socket = null;
    private BufferedReader in;
    PrintWriter out;
    public ATMServerThread(Socket socket) {
        super("ATMServerThread");
        this.socket = socket;
    }

    public void run(){
    try {
        out = new PrintWriter(socket.getOutputStream(), true);

        out.println("Welcome!"); 

    } catch (IOException e){
        e.printStackTrace();
        }
    }
}

Клиент:

import java.io.*;   
import java.net.*;  
import java.util.Scanner;

public class Client {
    private static int connectionPort = 8989;

    public static void main(String[] args) throws IOException {

        Socket ATMSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;
        String adress = "";

        try {
            adress = "127.0.0.1";
        } catch (ArrayIndexOutOfBoundsException e) {
            System.err.println("Missing argument ip-adress");
            System.exit(1);
        }
        try {
            ATMSocket = new Socket(adress, connectionPort); 
            out = new PrintWriter(ATMSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader
                                    (ATMSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Unknown host: " +adress);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't open connection to " + adress);
            System.exit(1);
        }

        System.out.println(in.readLine());


        out.close();
        in.close();
        ATMSocket.close();
    }
}

Ответы [ 5 ]

3 голосов
/ 03 ноября 2011

Это возможно, но не просто.

Строка "Добро пожаловать!" является частью файла класса (это статическая константа String). Когда вы его измените, Eclipse создаст новый файл .class и запишет его на диск.

В то же время у вас есть работающая программа на Java, которая использует тот же файл .class. Есть две причины, по которым изменение не получено:

  1. Виртуальная машина Java не перезагружает файлы классов самостоятельно. Когда класс был загружен один раз, он не обновляется при изменении файла .class на диске. Вы должны указать загрузчику классов очистить загруженный класс из памяти и снова загрузить файл .class.

  2. В работающей ВМ есть экземпляр этого класса. Экземпляр имеет ссылку на объект String. Даже когда класс загружается снова, этот экземпляр (и его ссылки) не изменяются. Вы должны создать новый экземпляр.

Чтобы решить первую проблему, вам нужно запустить приложение в режиме отладки. Затем Eclipse попытается сообщить виртуальной машине, когда изменились файлы .class. Обратите внимание, что некоторые изменения не могут быть перезагружены некоторыми виртуальными машинами. Например, виртуальная машина Sun может обрабатывать новые методы, параметры методов, поля, импорт. Вы можете изменить только тела метода. Eclipse сообщит вам, когда перезагрузка не удалась.

Чтобы устранить вторую проблему, остановите поток и начните новый. Для этого я предлагаю специальное клиентское сообщение «перезагрузить», которое останавливает все потоки и создает новый пул.

В любом случае, Eclipse никогда не нужно останавливать.

2 голосов
/ 03 ноября 2011

Я подозреваю, что вы неправильно поняли следующим образом -

  • вы нажали 'Run' в Eclipse, и ваш сервер запустил
  • тестируешь с клиентом
  • вы меняете сервер
  • вы снова нажали 'Run'
  • вы тестируете с клиентом и не видите изменений

В данном случае происходит следующее: во время второго запуска ваш сервер не запускается, так как предыдущий все еще работает и новый не может получить прослушивающий сокет.

Вам не нужно перезапускать Eclipse, чтобы прервать запущенный процесс, просто перейдите в представление консоли, используйте раскрывающийся список «Открыть консоль» (очень справа) на панели инструментов, чтобы найти запущенный процесс на сервере и остановить его, используя красная кнопка остановки (очень левая).

0 голосов
/ 03 ноября 2011

«Добавить динамический код Java в ваше приложение» http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html

0 голосов
/ 03 ноября 2011

Создайте метод set в вашем потоке для переменных, которые вы хотите изменить. Когда вы создаете экземпляр потока, сохраняйте дескриптор созданного вами потока. Затем просто вызовите метод установки для переменной.

0 голосов
/ 03 ноября 2011

Я не уверен, что полностью понимаю ваш вопрос, но мне кажется, я знаю, о чем вы говорите. Я считаю, что происходит то, что ваше приложение не закрывает сокет, когда вы его завершаете. В Windows я не уверен, что есть способ закрыть этот сокет вне процесса, который его открыл, но в Linux вы можете это сделать, и lsof затем убьет этот pid.

lsof -i tcp:8989
kill -9 some_PID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...