Java - 关于socket:如何在不重启服务器的情况下更改线程

时间:2011-11-03 12:33:23

标签: java sockets client-server

有关于服务器客户端的问题:

当服务器运行时,如果我想在ServerThread中进行一些更改,例如,字符串“Welcome!” “你好!”,是否可以在不重启服务器的情况下执行该操作?现在,当我改变“欢迎!”除此之外,它还打印出“欢迎!”对客户。我必须关闭eclipse并重新启动服务器以使这个新字符串正常工作。有什么方法可以解决这个问题吗?很多!

服务器:

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 个答案:

答案 0 :(得分:3)

这是可能的但不简单。

字符串“欢迎!”是类文件的一部分(它是一个静态的String常量)。当您更改它时,Eclipse将创建一个新的.class文件并将其写入磁盘。

同时,您有一个运行的Java程序,它使用相同的.class文件。有两个原因可以解决这一变化:

  1. Java VM本身不会重新加载类文件。当一个类加载一次后,当您更改磁盘上的.class文件时,它不会更新。您必须告诉类加载器从内存中刷新已加载的类并再次加载.class文件。

  2. 正在运行的VM中有此类的实例。该实例具有对String对象的引用。即使再次加载类,此实例(及其引用)也不会更改。您必须创建一个新实例。

  3. 要解决第一个问题,您需要在调试模式下运行应用程序。然后Eclipse将尝试告诉VM .class文件何时更改。请注意,某些VM无法重新加载某些更改。例如,Sun的VM可以处理新方法,方法参数,字段,导入。您只能更改方法体。 Eclipse将在重新加载失败时告诉您。

    要解决第二个问题,请停止该线程并开始一个新线程。我建议一个特殊的客户端“重启”消息,它会停止所有线程并创建一个新池。

    无论如何,永远不必停止Eclipse。

答案 1 :(得分:2)

我怀疑你误解了以下方式 -

  • 你在Eclipse中点击'Run',你的服务器启动
  • 您使用客户端进行测试
  • 您更改服务器
  • 你再次点击'Run'
  • 您使用客户端进行测试并且看不到任何更改

这里发生的是第二次点击运行时,您的服务器无法启动,因为前一个服务器仍在运行&所以新的无法获取监听套接字。

您无需重新启动Eclipse即可终止正在运行的进程,只需转到Console视图,使用工具栏中的“Open Console”下拉(非常右侧)查找正在运行的服务器进程并使用红色停止按钮(非常左)。

答案 2 :(得分:0)

在线程上为要更改的变量创建一个setter方法。实例化线程时,请保留您创建的线程的句柄。然后只需为变量调用setter方法。

答案 3 :(得分:0)

“向您的应用程序添加动态Java代码” http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html

答案 4 :(得分:-1)

我不确定我是否完全理解你的问题,但我想我知道你在说什么。我相信正在发生的事情是你的应用程序在你结束它时没有关闭套接字。在Windows中,我不确定是否有办法在打开它的进程外关闭该套接字,但在Linux中你可以做,然后lsof然后杀掉那个pid。

lsof -i tcp:8989
kill -9 some_PID